使用xpath查找节点集中节点的位置

phi*_*red 5 xml xpath nodesets position

玩弄后position()白白我周围的Googling的解决方案,并来到这个旧的计算器问题几乎描述了我的问题.

区别在于我希望其中的位置是动态的,而不是文档的连续部分.

为了说明我将修改链接问题中的示例以符合我的要求.请注意,每个<b>元素都在不同的<a>元素中.这是关键的一点.

<root>
    <a>
        <b>zyx</b>
    </a>
    <a>
        <b>wvu</b>
    </a>
    <a>
        <b>tsr</b>
    </a>
    <a>
        <b>qpo</b>
    </a>
</root>
Run Code Online (Sandbox Code Playgroud)

现在,如果我查询,使用XPath,a/b我将得到四个<b>节点的节点集.然后我想找到包含该字符串的节点的该节点集内的位置'tsr'.另一篇文章中的解决方案在这里分解:count(a/b[.='tsr']/preceding-sibling::*)+1返回1因为preceding-sibling导航文档而不是上下文节点集.

是否可以在上下文节点集中工作?

Dim*_*hev 5

这是一个通用解决方案,适用于属于同一文档中任何节点集的任何节点

我正在使用 XSLT 来实现该解决方案,但最终获得了一个可以与任何其他托管语言一起使用的 XPath 表达式。

$vNodeSet成为节点集,并$vNode成为这个节点集中我们想要找到其位置的节点。

然后, let$vPrecNodes包含前面的 XML 文档中的所有节点$vNode

然后, let$vAncNodes包含 XML 文档中作为$vNode.

在文档顺序$vNodeSet之前的节点集由节点集中$vNode的所有节点$vPrecNodes和节点集中的所有节点组成$vAncNodes

我将使用著名的 Kaysian 公式来计算两个节点集的交集:

$ns1[count(.|$ns2) = count($ns2)]

包含的交叉点完全节点$ns1$ns2

基于所有这些,让$vPrecInNodeSet是在文档顺序$vNodeSet之前的节点集$vNode。以下 XPath 表达式定义$vPrecInNodeSet

$vNodeSet
      [count(.|$vPrecNodes) = count($vPrecNodes)
      or
       count(.|$vAncNodes) = count($vAncNodes)
      ]
Run Code Online (Sandbox Code Playgroud)

最后,想要的位置是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>
Run Code Online (Sandbox Code Playgroud)

当上述转换应用于提供的 XML 文档时

<root>
    <a>
        <b>zyx</b>
    </a>
    <a>
        <b>wvu</b>
    </a>
    <a>
        <b>tsr</b>
    </a>
    <a>
        <b>qpo</b>
    </a>
</root>
Run Code Online (Sandbox Code Playgroud)

产生正确的结果

3

请注意:此解决方案不依赖于 XSLT(仅用于说明目的)。您可以组合一个 XPath 表达式,用它们的定义替换变量,直到没有更多的变量可以替换。


Ric*_*ard 0

你得到 1 的原因与上下文和文档无关,而是因为你只计算b一个a节点内的节点(所以你总是得到 0 的计数,因为从来没有任何前面的“b”节点。

相反,您需要找到包含“a”的“b”之前前面“a”节点的计数。

就像是:

count(a[b[.='tsr']]/preceding-sibling::a)
Run Code Online (Sandbox Code Playgroud)