6
votes

We have an xml node "item" with an attribute "style", which is "Header1". This style can change however. We have an attribute set named Header1 which defines how this should look in a PDF, generated through xsl:fo.

This works (the use-attribute-sets is mentioned inline, in the fo:table-cell node):

<xsl:template match="item[@type='label']">
    <fo:table-row>
        <fo:table-cell xsl:use-attribute-sets="Header1">            
             <fo:block>
                 <fo:inline font-size="8pt" >
                    <xsl:value-of select="." />
                </fo:inline>
            </fo:block>
        </fo:table-cell>
    </fo:table-row>
</xsl:template>

But this doesn't (using xsl:attribute, because the attribute @style can also be Header2 for example). It doesn't generate an error, the PDF is created, but the attributes aren't applied.

<xsl:template match="item[@type='label']">
    <fo:table-row>
        <fo:table-cell>         
             <xsl:attribute name="xsl:use-attribute-sets">
                 <xsl:value-of select="@style" />
             </xsl:attribute>
             <fo:block>
                 <fo:inline font-size="8pt" >
                    <xsl:value-of select="." />
                </fo:inline>
            </fo:block>
        </fo:table-cell>
    </fo:table-row>
</xsl:template>

Does anyone know why? And how we could achieve this, preferably without long xsl:if or xsl:when stuff?

3

3 Answers

6
votes

From http://www.w3.org/TR/xslt#attribute-sets

Attribute sets are used by specifying a use-attribute-sets attribute on xsl:element, xsl:copy [...] or xsl:attribute-set elements

From http://www.w3.org/TR/xslt#section-Creating-Elements-with-xsl:element

<!-- Category: instruction -->
<xsl:element
  name = { qname }
  namespace = { uri-reference }
  use-attribute-sets = qnames>
  <!-- Content: template -->
</xsl:element>

And http://www.w3.org/TR/xslt#copying

<!-- Category: instruction -->
<xsl:copy
  use-attribute-sets = qnames>
  <!-- Content: template -->
</xsl:copy>

So, it's clear it can't be an AVT (dynamicly defined).

Note: About literal result element, the specification say: Attribute sets can also be used by specifying an xsl:use-attribute-sets attribute on a literal result element. It's rare vague about allowing AVT. Assume no.

About second example: with that template you're adding a "xsl:use-attribute-sets" attribute into the result tree. It's not iterpreted by the XSLT processor.

Then, what's the solution? You have to get rid of "xsl:use-attribute-sets". Apply a template rule for "@style" and generate the desired attributes there.

0
votes

Try:

<fo:table-cell xsl:use-attribute-sets="{@style}">
0
votes

Use a variable to define style, a variable for true, a variable for false, and a variable to reference either one dynamically using string concatenation:

<xsl:variable name="style">
  <xsl:value-of select="concat(boolean(@style),boolean(not(@style) ) )"/>
</xsl:variable>

<xsl:variable name="falsetrue" select="'foo'"/>
<xsl:variable name="truefalse" select="'bar'"/>
<!--...-->


<xsl:value-of select="//xsl:variable/@select[../@name='style']"/>

Or you can have the templates match themselves and call them using the value of "style":

<xsl:template name="Header1" match="xsl:template[@name='Header1']"/>

<xsl:template name="Header2" match="xsl:template[@name='Header2']"/>