【问题标题】:ElementTree findall 'or' operatorElementTree findall 'or' 运算符
【发布时间】:2014-03-21 13:57:32
【问题描述】:

如果我有这样的 xml 文件:

<root>
  <item>
    <prop>something</prop>
  </item>
  <test>
    <prop>something</prop>
  </test>
  <test2>
    <prop>something</prop>
  </test2>
</root>

我可以使用 xmlTree.getroot().findall("item") 获取所有“项目”元素。

如何获得所有“项目”或“测试”元素?我想要类似的东西:

xmlTree.getroot().findall("item or test")

我在文档的示例中没有看到类似的内容。有什么想法吗?

【问题讨论】:

    标签: python elementtree


    【解决方案1】:

    由于 stdlib 中的ElementTree 仅提供有限的 xpath 支持,因此只有在使用 lxml 时才能使用 | xpath OR 运算符:

    from lxml import etree as ET
    
    
    data = """<?xml version="1.0"?>
    <data>
    <item>1</item>
    <test>2</test>
    </data>"""
    
    tree = ET.fromstring(data)
    
    for element in tree.xpath('//item|//test'):
        print element.text
    

    打印:

    1
    2
    

    如果是xml.etree.ElementTree,您可以合并两个单独的findall() 调用的结果:

    for element in tree.findall('.//item') + tree.findall('.//test'):
        print element.text
    

    或者,检查循环内的标签名称:

    for element in tree.iter():
        if element.tag in ('item', 'test'):
            print element.text
    

    【讨论】:

    • 我喜欢第一个带有 xpath 的版本。您的代码按指示工作。但是,我尝试将其更改为从文件中读取 xml:# -- coding: utf-8 -- import xml.etree.ElementTree as ET tree = ET.parse('data.xml ') for element in tree.xpath('//item|//test'): print element.text 但我得到 AttributeError: ElementTree instance has no attribute 'xpath' 我也尝试像这样使用 xpath 语法:root = tree.getroot() for element in root.findall('item|test'): print element.text 但是没有输出?
    • 啊,我现在看到了 lxml 和 xml.etree.ElementTree 之间的区别。它是这样工作的。这些模块之间还有其他区别吗?也就是说,如果我有其他使用 etree.ElementTree 编写的代码,如果我更改为 lxml,它会继续工作吗?
    • @DavidDoria 应该,但您可能需要稍微更改代码,请参阅差异here
    【解决方案2】:

    大型数据集的“通配符”解决方案

    这是一个不需要指定“A | B| ...”的解决方案。而是使用“*”作为通配符,并按如下代码所示的索引过滤掉不需要的部分(例如,在这个问题中,可以使用 lst[:-1] 排除最后一个标签“test2”)。

    import xml.etree.ElementTree as ET
    data='''
    <root>
      <item>
        <prop>something1</prop>
      </item>
      <test>
        <prop>something2</prop>
      </test>
      <test2>
        <prop>something3</prop>
      </test2>
    </root>'''
    root = ET.fromstring(data)
    lst = root.findall('*')
    for x in lst[:-1]:
        print(x.find('prop').text)
    

    输出:

    某事1

    某事2

    【讨论】:

      猜你喜欢
      • 2015-07-08
      • 1970-01-01
      • 1970-01-01
      • 2020-10-04
      • 2016-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多