鉴于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()与|工会运营商以及其他一些优秀的提示。
答案 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])]
?
但这只适用于您的情况,不确定它应该是多么通用!