查找子包含一些文本的非根父节点

时间:2013-11-19 16:27:43

标签: python xml xpath elementtree

我有一些xml;

<root>
    <parent>
        <child>foo987654</child>
    </parent>
    <parent>
        <child>bar15245</child>
    </parent>
    <parent>
        <child>baz87742</child>
    </parent>
    <parent>
        <child>foo123456</child>
    </parent>
</root>

我正在使用python和etree模块,我想选择孩子以“foo”开头的所有<parent>个节点。我知道etree有限的xpath支持,但我是一个xpath菜鸟,所以我很难找到最好的解决方案。我想到了这个效果

parent[(contains(child,'foo'))] 

但我想拒绝包含foo但不以foo开头的父节点(即<child>125456foo</child>),所以我不确定这会起作用。此外,我不确定etree是否支持此级别的xpath ...

编辑:

另一个可接受的解决方案是选择孩子的文本在列表中的父母。 伪代码 parent =&gt; child [text =“foo1”|| “bar1”|| “BAR2”]

这可能吗?

3 个答案:

答案 0 :(得分:4)

这将得到你想要的:

[elem for elem in root.findall('parent') if elem.find('child').text.startswith('foo')]

观看它的实际操作:

s = """<root>
    <parent>
        <child>foo987654</child>
    </parent>
    <parent>
        <child>bar15245</child>
    </parent>
    <parent>
        <child>baz87742</child>
    </parent>
    <parent>
        <child>foo123456</child>
    </parent>
</root>"""

import xml.etree.ElementTree as ET

root = ET.fromstring(s)
elems = [elem for elem in root.findall('parent') if elem.find('child').text.startswith('foo')]

检查数据:

for elem in elems:
    print elem.find('child').text
>>>
foo987654
foo123456

答案 1 :(得分:0)

xml.etree documentation可以看出,此库不支持XPath中的contains()运算符。我的建议是选择所有具有XPath /parent的子项,然后迭代每个结果以删除不以 foo 开头的子项内容。

答案 2 :(得分:0)

使用xpath

import lxml.html
doc = lxml.html.document_fromstring(s)
for e in doc.xpath(".//child[starts-with(text(), 'foo')]"):
    print e.text