A portable (XPath 1.0 and 2.0) solution would be:
<xsl:if test="
$currentNode/ancestor::*[generate-id() = generate-id($someNode)]
">
Write this out.
</xsl:if>
This walks up the ancestor axis and checks every element in it. If (and only if) the unique ID of one of the ancestors matches the unique ID of $someNode
, the resulting node-set is not empty.
Non-empty node-sets evaluate to true, so the condition is fulfilled.
Test - find all <baz>
that are descendant of <foo>
:
<xml>
<foo>
<bar>
<baz>Test 1</baz>
</bar>
</foo>
<baz>Test 2</baz>
</xml>
and
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="/">
<xsl:variable name="someNode" select="//foo[1]" />
<!-- test each <baz> node if it has <foo> as a parent -->
<xsl:for-each select="//baz">
<xsl:if test="
ancestor::*[generate-id() = generate-id($someNode)]
">
<xsl:copy-of select="." />
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
results in
<baz>Test 1</baz>
Note that if you are referring to the actual current node, like I do in the for-each, there is no need for a separate $currentNode
variable. All XPath is relative to the current node by default.
A variant would be the top-down way. It is less efficient though (probably by several orders of magnitude):
<xsl:if test="
$someNode[//*[generate-id() = generate-id($currentNode)]]
">
Write this out.
</xsl:if>