使用以下 XPath 1.0 表达式:
$v1/ancestor::*
[count(. | $v2/ancestor::*)
=
count($v2/ancestor::*)
]
[1]
其中 $v1 和 $v2 包含两个文本节点(如果您在 XSLT 之外使用 XPath,则必须将上述表达式中的 $v1 和 $v2 替换为 XPath 表达式选择这两个文本节点中的每一个)。
说明:
上面的 XPath 1.0 表达式找到两个节点集的交集:$v1 的所有元素祖先的节点集和 $v2 的所有元素祖先的节点集。 这是通过所谓的 Kaysian 交集方法完成的(在 Michael Kay 之后,他在 2000 年发现了这一点)。使用 Kaysian 方法进行交集,两个节点集 $ns1 和 $ns2 的交集通过以下 XPath 表达式选择:
$ns1[count(. | $ns2) = count($ns2)]
那么,我们必须从祖先的交点中选择最后一个元素。但是,因为我们使用的是反向轴(祖先),所以需要的节点位置必须表示为 1。
通过应用以下转换,可以快速验证上述 XPath 表达式是否确实选择了最低共同祖先:
<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>
应用于最初提供的 XML 文档时(更正为格式良好的 XML):
<outer>
<main>
<a>
<b>sometext</b>
</a>
<c>
<d>sometext2</d>
</c>
</main>
</outer>
想要的结果(两个文本节点的最低共同祖先元素的名称)产生:
主要
选择两个节点的最低共同祖先的 XPath 2.0 表达式更简单,因为它使用标准的 XPath 2.0 运算符“相交”:
($v1/ancestor::* intersect $v2/ancestor::*)
[last()]