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
The rules are in https://www.w3.org/TR/xslt-10/#creating-attributes:
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.
Answering the supplementary question:
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:
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.