Nothing is absolute

Yesterday I discovered that the XPath expression "/customers/customer" is not an absolute expression even though it looks like one (because it starts with a slash).

I learned this the hard way after struggling with an iteration over an XSLT 2.0 sequence.

The XSLT snippet

<xsl:for-each select="(1 to 3)">
  <xsl:value-of select="customer"/>
</xsl:for-each>

does not output the value of the element customer 3 times. Instead it generates the following error message:

Cannot select a node here: the context item is an atomic value

This makes sense because the XSLT 2.0 spec clearly states:

When the context item is an atomic value, there is no context node: its value is an empty sequence. The context node is returned by the XPath expression self::node(), and it is used as the starting node for all relative path expressions.

If you change the XSLT snippet to use an 'absolute' expression

<xsl:for-each select="(1 to 3)">
  <xsl:value-of select="/customers/customer"/>
</xsl:for-each>

it turns out that the error does not disappear. How is this possible?

I have found a clear explanation by Michael Kay:

Because "absolute paths" are not absolute at all: they select relative to
the root of the tree containing the context node. You've got to know which
document to look in.

A workaround was given in the same thread:

<xsl:variable name="tmp" select="/customers"/>
<xsl:for-each select="(1 to 3)">
  <xsl:value-of select="$tmp/customer"/>
</xsl:for-each>

This will give you the expected output: 3 times the value of the element customer.

Topic: 

1 Comment

Add new comment