【问题标题】:How do I iterate over a xml file recursively and access the child nodes/elements and store their data using Python?如何递归地遍历 xml 文件并访问子节点/元素并使用 Python 存储它们的数据?
【发布时间】:2020-08-01 20:17:28
【问题描述】:

我有一个如下所示的 XML 文件。现在我需要访问port->nameport->wire->directionport->wire->driver->defval。 XML 文件非常大。

我该如何处理?

<spirit:Bus> 
    <spirit:Ports>   
        <spirit:port>
            <spirit:name>ABCPORT</spirit:name>
            <spirit:description>SOME DESCRIPTION</spirit:description>
            <spirit:wire>
                <spirit:direction>INPUT</spirit:direction>
                <spirit:driver>
                    <spirit:defaultValue>0</spirit:defaultValue>
                </spirit:driver>
            </spirit:wire>
        </spirit:port>
        <spirit:port>
            <spirit:name>PQRPORT</spirit:name>
            <spirit:description>SOME DESCRIPTION</spirit:description>
            <spirit:wire>
                <spirit:direction>OUTPUT</spirit:direction>
            </spirit:wire>
        </spirit:port>        
    </spirit:ports>
</spirit:Bus>

【问题讨论】:

  • ElementTree 在标准库中。见docs.python.org/3/library/xml.etree.elementtree.html。如果您对如何使用它有疑问,请将您的问题与您尝试过的代码一起发布。
  • 你想要的输出是0吗?
  • 我想要类似的东西 - Port-ABCPORT, Direction-Input,Default value-0;Port-PQRPORT, Direction-Output。

标签: python xml xml-parsing elementtree


【解决方案1】:

为了正确格式化 XML,我将命名空间添加到您的示例中:

<spirit:Bus xmlns:spirit="http://dummy.com">
    ...
</spirit:Bus>

Bus 仍然是根节点,就像在您的示例中一样。 当然,您可以将给定的 URL 更改为您想要的任何内容。

要仅在 ElementTree 中完成您的任务,您可以使用以下代码:

import xml.etree.ElementTree as et

tree = et.parse('Input.xml')
root = tree.getroot()
ns = {'spirit': 'http://dummy.com'}
for nd in root.findall('spirit:Ports/spirit:port', ns):
    print(nd.tag.split('}')[1], nd.findtext('spirit:name', namespaces=ns),
        nd.findtext('spirit:wire/spirit:direction', namespaces=ns),
        nd.findtext('spirit:wire/spirit:driver/spirit:defaultValue', namespaces=ns))

请注意,您的 XML 包含命名空间规范,因此您还拥有 在代码中指定。

我的代码还展示了如何获取节点的本地名称(没有命名空间)。

您的样本的结果是:

port ABCPORT INPUT 0
port PQRPORT OUTPUT None

【讨论】:

    【解决方案2】:

    我相信解决这个问题的最好方法是使用 lxml 和 xpath:

    from lxml import etree
    
    #the xml below is somewhat different than the one in the question, because of a type and the declare namespaces
    
    spirit = """<?xml version="1.0" encoding="UTF-8"?>
    <doc xmlns:spirit="http://example.com">
       <spirit:Bus>
          <spirit:Ports>
             <spirit:port>
                <spirit:name>ABCPORT</spirit:name>
                <spirit:description>SOME DESCRIPTION</spirit:description>
                <spirit:wire>
                   <spirit:direction>INPUT</spirit:direction>
                   <spirit:driver>
                      <spirit:defaultValue>0</spirit:defaultValue>
                   </spirit:driver>
                </spirit:wire>
             </spirit:port>
             <spirit:port>
                <spirit:name>PQRPORT</spirit:name>
                <spirit:description>SOME DESCRIPTION</spirit:description>
                <spirit:wire>
                   <spirit:direction>OUTPUT</spirit:direction>
                </spirit:wire>
             </spirit:port>
          </spirit:Ports>
       </spirit:Bus>
    </doc>
    """
    
    doc = etree.XML(spirit.encode('utf-8'))
    ports = doc.xpath('//*[local-name()="port"]')
    for port in ports:
        try:
            print("Port-",port.xpath('.//*[local-name()="name"]')[0].text)
            print("Direction",port.xpath('.//*[local-name()="direction"]')[0].text)
            print("Default value",port.xpath('.//*[local-name()="defaultValue"]')[0].text)
        except:
            continue
    

    输出:

    Port- ABCPORT
    Direction INPUT
    Default value 0
    Port- PQRPORT
    Direction OUTPUT
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-04
      • 2014-04-20
      • 2023-03-14
      • 1970-01-01
      • 2019-06-23
      • 2020-07-07
      • 2023-03-12
      • 1970-01-01
      相关资源
      最近更新 更多