This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 28888 - [xslt 3.0] xsl:on-empty with xsl:value-of
Summary: [xslt 3.0] xsl:on-empty with xsl:value-of
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 3.0 (show other bugs)
Version: Last Call drafts
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Michael Kay
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-07-03 09:23 UTC by Michael Kay
Modified: 2015-08-17 08:37 UTC (History)
1 user (show)

See Also:


Attachments

Description Michael Kay 2015-07-03 09:23:19 UTC
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.
Comment 1 Michael Kay 2015-07-03 10:01:29 UTC
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...
Comment 2 Michael Kay 2015-07-09 17:31:01 UTC
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.
Comment 3 Michael Kay 2015-07-09 23:49:01 UTC
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].
Comment 4 Michael Kay 2015-07-23 17:25:02 UTC
The proposal was accepted.
Comment 5 Michael Kay 2015-08-17 08:37:33 UTC
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.