Use the following XPath 1.0 expression :
$v1/ancestor::* [count(. | $v2/ancestor::*) = count($v2/ancestor::*) ] [1]
, where $ v1 and $ v2 contain two text nodes (if you are not using XPath in XSLT, you will have to replace $ v1 and $ v2 in the above expression with XPath expressions that select each of these two text nodes).
Explanation
The above XPath 1.0 expression finds the intersection of two node-sets : node -set of all the ancestors of the element $ v1 and node -set of all the ancestors of the elements of $ v2. This is done using the so-called Kaysian method for crossing (after Michael Kay, who discovered this in 2000). Using the Kaysian method to intersect, the intersection of two nodes, $ ns1 and $ ns2, is selected with the following XPath expression :
$ns1[count(. | $ns2) = count($ns2)]
Then from the intersection of the ancestors, we must select the last element . However , because we use the back axis (ancestor), the required node position must be indicated as 1 .
You can quickly verify that the above XPath expression actually selects the smallest common ancestor using the following transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:variable name="v1" select="/*/*/a/b/text()"/> <xsl:variable name="v2" select="/*/*/c/d/text()"/> <xsl:variable name="vCommonAncestor" select= "$v1/ancestor::* [count(. | $v2/ancestor::*) = count($v2/ancestor::*) ] [1]" /> <xsl:template match="/"> <xsl:value-of select="name($vCommonAncestor)"/> </xsl:template> </xsl:stylesheet>
when applied to the originally provided XML document (fixed for correct XML):
<outer> <main> <a> <b>sometext</b> </a> <c> <d>sometext2</d> </c> </main> </outer>
the desired result (the name of the element that is the smallest common ancestor of two text nodes) is created :
Main
An XPath 2.0 expression that selects the lowest common ancestor of two nodes is simpler because it uses the standard XPath 2.0 "intersect" statement:
($v1/ancestor::* intersect $v2/ancestor::*) [last()]