XPath用于查找包含具有特定值属性的元素的最近祖先元素

时间:2010-06-09 11:32:03

标签: xpath

ancestor::foo[bar[@attr="val"]]

我认为这会奏效,但事实并非如此。我需要找到树中具有foo子元素的最近的bar元素,该元素的attr属性为val

4 个答案:

答案 0 :(得分:33)

这应该有效:

//*[ancestor::foo[bar[@attr="val"]]]

或者

root/foo/bar[ancestor::foo[bar[@attr="val"]]]

匹配第二个<bar>元素

<root>
    <foo>
        <bar attr="xxx"></bar>
    </foo>
    <foo>
        <bar attr="val"></bar>
    </foo>
    <foo>
        <bar attr="zzz"></bar>
    </foo>
</root>

答案 1 :(得分:11)

已更新,以反映OP预期的解决方案。

请参阅@ David的回答

对于下面的xml示例,

<root>
<foo id="0">
    <bar attr="val"/>
    <foo id="1">
        <bar attr="xxx"/>
    </foo>
    <foo id="2">
        <bar attr="val">
            <one>1</one>
            <two>
                <three>3</three>
            </two>
        </bar>
    </foo>
</foo>

反轴上的有效xpath,其中&lt; 3&gt;作为上下文节点,有效的解决方案是

./ancestor::foo[bar[@attr='val']][position() = 1]

&#34; ./" 是可选的。 position()= 1不是可选的,否则也会返回满足谓词的祖先foo

旧答案:忽略

这是一个老问题。但是任何有兴趣的人,以下内容都应该让你了解原始问题的意图。

反转轴

//bar[@attr='val']/ancestor::*[position()=1]

前轴

//*[child::bar[@attr='val']]

答案 2 :(得分:1)

在我看来,最佳答案是由提出问题的人提供的。他的解决方案应该归还所有的祖先。他只想要最近的一个是position()= 1的那个,所以他的xpath表达式需要稍微修改为:

ancestor::foo[bar[@attr="val"] and position() = 1]

如果他写道ancestor::foo[bar[@attr="val"]]没有返回任何内容,那么他​​的xml中或者他对XPath评估上下文的当前元素的假设有其他问题。

其他答案(以//开头)并没有真正回答这个问题,即使他们偶然遇到某人的需要,所以他们效率不高: 他们选择xml文件中的所有元素,然后对它们应用过滤器。 虽然我或提出这个问题的人提出的相对xpath只是搜索从当前节点开始到父节点及其父节点等的几个元素 - 即使使用大型XML文件也会非常有效。

答案 3 :(得分:0)

如果您有这样的文件:

<root>                                                                                                             
<foo id="0">                                                                                                       
    <foo id="1">                                                                                                   
        <bar attr="xxx" />                                                                                         
    </foo>                                                                                                         
    <foo id="2">                                                                                                   
        <bar attr="val" />                                                                                         
    </foo>                                                                                                         
    <foo id="3">                                                                                                   
        <tar>                                                                                                      
            <bar attr="val" />                                                                                     
        </tar>                                                                                                     
    </foo>                                                                                                         
</foo>                                                                                                             
</root>

,并且您希望foo节点具有ID​​ 23,即与其具有foos的{​​{1}}后代最接近的bar ,以下作品:

attr=val

如果省略//foo[descendant::bar[@attr="val"] and not(descendant::foo)] ,则另外获得and not(descendant::foo),其ID为foo

在我的示例一般情况下,其他答案对我不起作用。

您可以使用以下命令在Python中进行测试:

0

打印:

from lxml import etree
tree = etree.parse('example.xml')
foos = tree.xpath('//foo[descendant::bar[@attr="val"] and not(descendant::foo)]')
for foo in foos:
    print(foo.attrib)

请注意,使用的xpath效率不高。我想学习一种更有效的方法。