获取带有属性的etree元素,或包含带属性的子元素

时间:2016-07-19 18:12:26

标签: python xml elementtree

我有一个要解析的XML文件,我需要按id找到元素。

在示例代码中,我需要找到driver的名称,但我不知道我的ID是用于vehicleengine还是{{1 }}。我想要一个可以在block内使用任意xml的解决方案(但保证存在vehicle)。

driver

我尝试了什么

我试图通过他们的id来获取元素,然后,如果它们不是<road> <vehicle id="16"> <driver>Bob Johnson</driver> <engine id="532"> <type>V8</type> <block id="113"> <material>Aluminium</material> </block> </engine> </vehicle> <vehicle id="452"> <driver>Dave Edwards</driver> <engine id="212"> <type>Inline 6</type> <block id="381"> <material>Cast Iron</material> </block> </engine> </vehicle> </road> 标签,则向上导航树以找到它,但似乎python的vehicle返回None如果结果在elem.find()之外。

查看the docs,他们有这个例子:

elem

但我不知道如何为任何后代做出这项工作,而不是特定级别的后代。

2 个答案:

答案 0 :(得分:1)

注意:以下所有代码段都使用lxml库。要安装,请运行:pip install lxml

您应该使用root.xpath(..)而不是root.findall(..)

>>> root.xpath("//vehicle/driver/text()")
['Bob Johnson', 'Dave Edwards']

如果你想从给定的ID中提取驱动程序的名称,你可以这样做:

>>> vehicle_id = "16"
>>> xpath("//vehicle[@id='16' or .//*[@id='16']]/driver/text()")
['Bob Johnson']

更新:要获得更深层次嵌套的给定id的驱动程序名称,您可以这样做:

>>> i = '16'
>>> a.xpath("//vehicle[@id='%s' or .//*[@id='%s']]/driver/text()"%(i,i))
['Bob Johnson']
>>> i = '532'
>>> a.xpath("//vehicle[@id='%s' or .//*[@id='%s']]/driver/text()"%(i,i))
['Bob Johnson']
>>> i = '113'
>>> a.xpath("//vehicle[@id='%s' or .//*[@id='%s']]/driver/text()"%(i,i))
['Bob Johnson']

答案 1 :(得分:1)

如果您知道id,但不知道此id是来自车辆,引擎还是阻止,您可以使用XPath表达式进行处理,但您必须使用lxml.etree代替xml.etree.ElementTree(它的XPath支持非常有限)。使用ancestor-or-self轴:

input_id = "your ID"
print(root.xpath(".//*[@id='%s']/ancestor-or-self::vehicle/driver" % input_id)[0].text)

这将打印:

  • Bob Johnson如果input_id16532113
  • Dave Edwards如果input_id452212381

完整的工作示例:

import lxml.etree as ET

data = """
<road>
    <vehicle id="16">
        <driver>Bob Johnson</driver>
        <engine id="532">
            <type>V8</type>
            <block id="113">
                <material>Aluminium</material>
            </block>
        </engine>
    </vehicle>
    <vehicle id="452">
        <driver>Dave Edwards</driver>
        <engine id="212">
            <type>Inline 6</type>
            <block id="381">
                <material>Cast Iron</material>
            </block>
        </engine>
    </vehicle>
</road>
"""

root = ET.fromstring(data)
for input_id in [16, 532, 113, 452, 212, 381]:
    print(root.xpath(".//*[@id='%s']/ancestor-or-self::vehicle/driver" % input_id)[0].text)

打印:

Bob Johnson
Bob Johnson
Bob Johnson
Dave Edwards
Dave Edwards
Dave Edwards