Search code examples
xmlxsltxsl-foapache-fop

How to query an attribute on an existing XSLT-FO output node


I am trying to create PDFs from HTML. I want to keep contents together on rows that do not contain child tables. I have located the appropriate rows but nothing happens, so I logged the output as follows:

  <xsl:template match="tr">
    <fo:table-row">
      <xsl:if test="count(descendant::table) = 0">
          <xsl:attribute name="keep-together">  
            <xsl:value-of select="always"/>  
          </xsl:attribute>
       </xsl:if>
      <xsl:message>
        keep-together = <xsl:value-of select="./@keep-together"/>
      </xsl:message>

For each row in the doc, the FOP logging says:

keep-together = 

So, I tried:

<xsl:template match="tr">
  <fo:table-row keep-together="always">
    <xsl:message>
      keep-together = <xsl:value-of select="./@keep-together"/>
    </xsl:message>

This makes jibberish of the output with the nested tables, but in the logging for each table-row it still says:

keep-together = 

So, how does one get the value of a newly-created attribute on a newly-created FO output node?


Solution

  • You can select nodes in the input document, not in the result document. If you store temporary results in a variable then with XSLT 2 or 3 you can also directly select nodes in the variable, or with XSLT 1 you would first need to use an extension function like exsl:node-set on the variable to convert it to a node set and to be able to apply XPath on it.

    <xsl:template match="tr">
      <xsl:variable name="row">
            <fo:table-row>
                <xsl:if test="descendant::table">
                    <xsl:attribute name="keep-together">always</xsl:attribute>
                </xsl:if>
                <xsl:apply-templates/>
            </fo:table-row>
      </xsl:variable>
      <xsl:message select="$row/fo:table-row/@keep-together"/>
      <xsl:copy-of select="$row"/>
    </xsl:template>