I am using xsl:evaluate
to evaluate xpaths. However, the result is different to if I directly evaluate xpaths, because in the latter case I can get access to the ancestors of the results but in the former I can't.
Is there any way to retain information about the context of the results of <xsl:evaluate>
?
Here is my XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="/one">
<xsl:value-of select="name()" />
<xsl:text>
</xsl:text>
<xsl:variable name="xpath">
<xsl:text>//three</xsl:text>
</xsl:variable>
<xsl:variable name="matches1">
<xsl:evaluate xpath="$xpath" context-item="." />
</xsl:variable>
<xsl:for-each select="$matches1/*">
<xsl:value-of select="name()" />
<xsl:text>,</xsl:text>
<xsl:value-of select="name(parent::*)" />
<xsl:text>
</xsl:text>
</xsl:for-each>
<xsl:variable name="matches2" select="//three" />
<xsl:for-each select="$matches2">
<xsl:value-of select="name()" />
<xsl:text>,</xsl:text>
<xsl:value-of select="name(parent::*)" />
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Here is the input file:
<one>
<two>
<three />
<three />
</two>
<two />
</one>
and here is the output:
one
three,
three,
three,two
three,two
Use
<xsl:variable name="matches1" as="item()*">
<xsl:evaluate xpath="$xpath" context-item="." />
</xsl:variable>
It has really nothing to do with xsl:evaluate
but rather how xsl:variable
(and xsl:param
) work in XSLT 2 and later, mainly due to backwards compatibility as to how things worked in XSLT 1; if you don't provide an as
attribute you are creating a new document node (https://www.w3.org/TR/xslt-30/#temporary-trees) that is populated by a copy of the items/nodes returned by the sequence constructor inside, i.e. in your case by the nodes selected/returned by xsl:evaluate
. If you provide as="item()*"
(or for your case of nodes you could also use as="node()*"
) then no new document node is constructed and populated but the variable is rather bound directly to the items/nodes returned by the sequence constructor (i.e. in your case the xsl:evaluate
) inside.
The gory details are in the XSLT 2 and 3 spec https://www.w3.org/TR/xslt-30/#variable-values and in Michael Kay's XSLT bible https://www.oreilly.com/library/view/xslt-20-and/9780470192740/.