This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.
Given the following: <a> <xsl:value-of select="@href"/> <xsl:on-empty select="'(no link)'"/> </a> users might find it surprising that if there is no @href attribute, the result will be the empty element <a/>. The reason is that in this situation the result of the xsl:value-of instruction is a text node whose string value is zero length; it is not an empty sequence. Therefore as far as xsl:on-empty is concerned, the result of the sequence constructor is non-empty. Zero-length text nodes are ignored in the rules for constructing complex content (e.g. the content of the a element) but they are not ignored for the purposes of xsl:on-empty. It's complicated by the fact that zero-length text nodes are not ignored everywhere, e.g in the body of xsl:variable or xsl:function: <xsl:variable name="x" as="item()*"> <xsl:value-of select="@href"/> <xsl:on-empty select="'(no link)'"/> </xsl:variable> Simply changing the rule so that xsl:on-empty ignores zero-length text nodes gives streamability problems with, for example, <xsl:variable name="x" as="item()*"> <xsl:on-empty select="'(no link)'"/> <xsl:value-of select="@href"/> <xsl:value-of select="@href"/> <xsl:value-of select="a"/> </xsl:variable> where the result of on-empty needs to be inserted into the result sequence before the three zero-length text nodes, but we can't evaluate it until the end. There is a workaround, which is to write <a> <xsl:conditional-content> <xsl:value-of select="@href"/> </xsl:conditional-content> <xsl:on-empty select="'(no link)'"/> </a> but it's not pretty.
Another workaround is: <a> <xsl:sequence select="data(@href)"/> <xsl:on-empty select="'(no link)'"/> </a> Perhaps we just need to give all users a brain transplant...
In discussion today, there was some sentiment to changing the rule for xsl:on-empty so that it ignores zero-length text nodes, but at the same time changing the rules so that xsl:on-empty must come at the end of the sequence constructor.
I propose the following changes: (a) if an xsl:on-empty instruction appears in a sequence constructor then (i) it must be the only xsl:on-empty instruction in the sequence constructor, and (ii) it must not be followed by any other instructions, with the exception of xsl:fallback. (It may however be followed by non-instructions such as xsl:catch if the context permits). (b) an xsl:on-empty instruction is evaluated if and only if there is no preceding instruction in the sequence constructor whose evaluation produces a substantive result. For this purpose a result is substantive if it is not any of the following: b(i) an empty sequence b(ii) a text node whose string value is zero length b(iii) a document node having no children [Note: the significance of these choices is that these values have no effect in the common case where the sequence constructor is used for constructing the content of nodes: see *Constructing complex content* and *Constructing simple content*.] (c) xsl:on-non-empty can continue to appear anywhere, and repeatedly. The rules change to: an xsl:on-non-empty instruction is evaluated if and only if there is an instruction in the sequence constructor, other than an xsl:on-empty or xsl:on-non-empty instruction, whose evaluation produces a substantive result [defined as above].
The proposal was accepted.
The change has been applied to the spec. I included one minor correction: the result of an instruction is treated as empty not only if it IS a zero-length text node or childless document node, but also if it CONSISTS ENTIRELY of such nodes.