这是一个通用解决方案,适用于属于同一文档中任何节点集的任何节点:
我正在使用 XSLT 来实现该解决方案,但最终获得了可以与任何其他宿主语言一起使用的单个 XPath 表达式。
设$vNodeSet
为节点集,$vNode
为该节点集中我们要查找其位置的节点。
然后, let$vPrecNodes
包含前面的 XML 文档中的所有节点$vNode
。
然后, let$vAncNodes
包含 XML 文档中的所有节点,它们是$vNode
.
以文档顺序排列在$vNodeSet
前面的节点集由节点集中也属于的所有节点和节点集中也属于的所有节点组成。$vNode
$vPrecNodes
$vAncNodes
我将使用著名的 Kaysian 公式计算两个节点集的交集:
$ns1[count(.|$ns2) = count($ns2)]
恰好包含与 的交点中的$ns1
节点$ns2
。
基于所有这些,let是文档顺序$vPrecInNodeSet
中的节点集。以下 XPath 表达式定义:$vNodeSet
$vNode
$vPrecInNodeSet
$vNodeSet
[count(.|$vPrecNodes) = count($vPrecNodes)
or
count(.|$vAncNodes) = count($vAncNodes)
]
最后,想要的位置是:count($vPrecInNodeSet) +1
以下是这一切如何协同工作:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="vNodeSet" select="/*/a/b"/>
<xsl:variable name="vNode" select="$vNodeSet[. = 'tsr'][1]"/>
<xsl:variable name="vPrecNodes" select="$vNode/preceding::node()"/>
<xsl:variable name="vAncNodes" select="$vNode/ancestor::node()"/>
<xsl:variable name="vPrecInNodeSet" select=
"$vNodeSet
[count(.|$vPrecNodes) = count($vPrecNodes)
or
count(.|$vAncNodes) = count($vAncNodes)
]
"/>
<xsl:template match="/">
<xsl:value-of select="count($vPrecInNodeSet) +1"/>
</xsl:template>
</xsl:stylesheet>
当对提供的 XML 文档应用上述转换时:
<root>
<a>
<b>zyx</b>
</a>
<a>
<b>wvu</b>
</a>
<a>
<b>tsr</b>
</a>
<a>
<b>qpo</b>
</a>
</root>
产生正确的结果:
3
请注意:此解决方案不依赖于 XSLT(仅用于说明目的)。您可以组装一个 XPath 表达式,用它们的定义替换变量,直到没有更多的变量可以替换。