XPath:限制结果集的范围

时间:2011-01-10 20:46:01

标签: xpath

鉴于XML

<a>
    <c>
        <b id="1" value="noob"/>
    </c>
    <b id="2" value="tube"/>
    <a>
        <c>
            <b id="3" value="foo"/>
        </c>
        <b id="4" value="goo"/>
        <b id="5" value="noob"/>
        <a>
            <b id="6" value="near"/>
            <b id="7" value="bar"/>
        </a>
    </a>
</a>

和Xpath 1.0查询

//b[@id=2]/ancestor::a[1]//b[@value="noob"]

上面的Xpath返回节点ID 1和5.目标是将结果限制为只有节点id = 1,因为它是唯一的@value="noob"元素,它是同一<a>的后代。 (//b[@id=2])也是。{/ p>的后代

换句话说,“查找所有 b 元素,其值是”noob“,它们是 a 元素的后代,后者也有一个id为2的后代,但是不是任何其他 a 元素的后代“。如此令人费解?实际上,id号和值是可变的,并且会有数百种节点类型。

如果id = 2,我们希望返回元素id = 1而不是id = 5,因为它包含在另一个元素中。如果id = 4,我们希望返回id = 5,但不是id = 1,因为它不是第一个祖先的元素,因为id = 4。

修改 基于Dimitre和Alejandro的评论,我发现了this有用的博客文章,解释了count()与|工会运营商以及其他一些优秀的提示。

3 个答案:

答案 0 :(得分:2)

首先,这个

  

是否有某种方法可以限制结果   设置为仅<b>元素   直接的孩子<a>   起始节点的元素   (//b[@id=2])?

//b[@value='noob'][ancestor::a[1]/b/@id=2]

它与:

不一样
  

从id等于的节点开始   到2,找到所有的元素   值是作为后代的“noob”   直接父c元素   没有经过另一个c   元件

这是:

//c[b/@id=2]//*[.='noob'][ancestor::c[1][b/@id=2]]

除了这些表达式,当您处理“上下文标记”时,您可以使用集合的成员资格测试,如下所示:

$node[count(.|$node-set)=count($node-set)]

我将这个案例用作练习......

答案 1 :(得分:2)

使用

//b[@value='noob']
      [count(ancestor::a[1] | //b[@id=2]/ancestor::a[1]) = 1]

<强>解释

第二个谓词确保两个b元素具有相同的最近祖先a

记住:在XPath 1.0中,节点标识的测试是:

count($n1 | $n2) = 1

答案 2 :(得分:0)

//b[@id=2]/ancestor::a[1]//b[@value="noob" and not(ancestor::a[2]=//b[@id=2]/ancestor::a[1])]? 但这只适用于您的情况,不确定它应该是多么通用!