skip to Main Content

I’m working on an XSLT transformation to create an HTML <button> element with an onclick attribute. When I define the onclick attribute before the button’s text content, everything works as expected. Here’s the code that works:

<xsl:element name="button">
    <xsl:attribute name="onclick">
        console.log(600);
    </xsl:attribute>
    
    <xsl:text>Click Me</xsl:text>
</xsl:element>

Output:

<button onclick="console.log(600);">Click Me</button>

However, if I place the xsl:attribute after the xsl:text content, like this:

<xsl:element name="button">
    <xsl:text>Click Me</xsl:text>

    <xsl:attribute name="onclick">
        console.log(600);
    </xsl:attribute>
</xsl:element>

The attribute is ignored, and the output only contains the text:

<button>Click Me</button>

Why does placing xsl:attribute after xsl:text cause the attribute to disappear? Is there a rule in XSLT that requires attributes to be defined before content, and if so, what’s the reasoning behind it? And why does it behave this way?

2

Answers


  1. The rules are in https://www.w3.org/TR/xslt-10/#creating-attributes:

    The following are all errors:

    Adding an attribute to an element after children have been added to
    it; implementations may either signal the error or ignore the
    attribute.

    So yes, you need to output attributes before any child nodes (like a text node), otherwise you might get an error or your XSLT processor ignores the attribute.

    Login or Signup to reply.
  2. Answering the supplementary question:

    and if so, what’s the reasoning behind it?

    The reasoning is that XSLT processors can and often do write output directly to the serialized output stream, bypassing the construction of a result tree. And (despite the fact that the spec doesn’t mandate it) they usually execute instructions in the order written, top to bottom. So the language is designed to make it easy for a processor that executes instructions sequentially to create output sequentially.

    The XSLT 1.0 spec uses temporal language rather liberally: "Adding an attribute to an element after children have been added to it". Subsequent versions try to avoid this. In XSLT 2.0 the rule becomes:

    [ERR XTDE0410] It is a non-recoverable dynamic error if the result
    sequence used to construct the content of an element node contains a
    namespace node or attribute node that is preceded in the sequence by a
    node that is neither a namespace node nor an attribute node.

    Note also that XSLT 2.0 requires the processor to throw an error, the option to ignore the attribute has gone. XSLT 2.0 tried (a) to make processors more interoperable, and (b) to require more user errors to be reported, rather than resulting in fallback action.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search