Reputation: 5754
Can anyone explain this to me? (using latest libxslt):
<a><xsl:copy-of select="(@attrib|exsl:node-set(0))"/></a>
<b><xsl:copy-of select="(@attrib|exsl:node-set(0))[position()=1]"/></b>
<x><xsl:copy-of select="(@attrib|exsl:node-set(0))[1]"/></x>
<xsl:variable name="value" select="@attrib"/>
<y><xsl:copy-of select="($value|exsl:node-set(0))[1]"/></y>
Result (for @attrib = 1 at current node):
<a attrib="1">0</a>
<b attrib="1"/>
<x>0</x>
<y attrib="1"/>
<a>
and <b>
show expected behavior.
<x>
is IMHO incorrect.
But why does putting @attrib
into a variable "fix" it for <y>
?
BTW: Everything is correct when @attrib is
not present. The copy-of used here is for debugging; original usage converts the XPath result to a number, and a missing attribute shall not lead to NaN, but a certain default value.
Upvotes: 0
Views: 321
Reputation: 243579
From a comment of the OP:
Ok, that means my only option is using
<xsl:choose>
..., correct?
While the way you attempt it produces unpredictable results due to reasons explained both by @Michael Kay and by me in my comments, there are still ways to do what you want (produce either the value of the attrib
attribute or a default value (0
):
concat(@attrib,
substring(0, 2 -not(@attrib))
)
This produces the value of the attrib
attribute (if this attribute is present) or (if not present) the default value 0
.
Complete XSLT solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="x">
<xsl:value-of select=
"concat(@attrib,
substring('0', 2 -not(@attrib))
)"/>
==========
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the following XML document:
<t>
<x attrib="abc"/>
<x/>
</t>
the wanted, correct result is produced:
abc
==========
0
==========
Upvotes: 1
Reputation: 163595
This version of exsl:node-set() presumably creates a node that is in a different tree from from the node @attrib. When two nodes are in different trees, it is implementation-dependent which of them comes first in document order. The construct (X|Y)[position()=1]
(or equivalently (X|Y)[1]
) selects whichever of X and Y comes first in document order. Therefore it's essentially unpredictable whether it selects X or Y.
Upvotes: 1