首页 > 解决方案 > 如何使用 Python 中的 ElementTree 删除带有 iterparse 的 XML 部分?

问题描述

我有多个大文件需要导入并遍历它们——它们都是 xmls 并且具有相同的树结构。结构是这样的,除了 ID 之外还有一些额外的文本,所以在 Start 下有更多的子元素标签:我想做的是输入一个我知道是错误的 Id 列表,然后从整个 XML 文件。一份报告在两个“T”之间。

<Header>
        <Header2>
           <Header3>
           <T>
              <Start> 
                <Id>abcd</Id>
              </Start>
           </T>
           <T>
              <Start> 
                <Id>qrlf</Id>
              </Start>
           </T>
           </Header3>
        </Header2>
</Header>

到目前为止我所拥有的:

from xml.etree import cElementTree as ET

file_path = '/path/to/my_xml.xml'
to_remove = []
root = None
for event, elem in ET.iterparse(file_path, events=("start", "end")):
if event == 'end':
    if elem.tag == 'Id':
        new_root = elem
        #print([elem.tag for elem in new_root.iter()])
        for elem2 in new_root.iter('Id'):
             id = elem2.text
             if id =='abcd':
                print(id)
                to_remove.append(new_root)
root = elem
for item in to_remove:
    root.remove(item)

因此,上面的代码显然不起作用,因为根是以 Header 开头的整个 xml 文件,并且它无法准确找到我所指的删除子元素,因为它的父级是 Header3 而不是 Header。

所以所需的输出将是:

<Header>
        <Header2>
           <Header3>
           <T>
              <Start> 
                <Id>qrlf</Id>
              </Start>
           </T>
           </Header3>
        </Header2>
</Header>

展望未来,我要输入删除的不是单个值,而是数千个值,所以要成为一个列表,我只是认为以这种方式表示问题更容易。任何帮助表示赞赏。

标签: xmlpython-3.xelementtreecelementtreeiterparse

解决方案


由于您的 XML 结构很简单,因此使用 Xpath 可能更容易(大约是https://docs.python.org/3/library/xml.etree.elementtree.html的 1/3 )。以下是文档页面该部分的使用示例:

import xml.etree.ElementTree as ET

root = ET.fromstring(countrydata)

# Top-level elements
root.findall(".")

# All 'neighbor' grand-children of 'country' children of the top-level
# elements
root.findall("./country/neighbor")

# Nodes with name='Singapore' that have a 'year' child
root.findall(".//year/..[@name='Singapore']")

# 'year' nodes that are children of nodes with name='Singapore'
root.findall(".//*[@name='Singapore']/year")

# All 'neighbor' nodes that are the second child of their parent
root.findall(".//neighbor[2]")

用于示例的 XML 结构可以在文档页面的顶部找到。

第二个示例显示了一种选择要删除的子元素的简单方法(在您的情况下为“T”),但在您的情况下,最后一种情况可能更有用。但是请参阅示例下方出现的 Xpath 语法部分中的 [tag='text'] 操作。
将该操作的结果发送到删除操作(页面向下约 3/4),然后是 XMLtree 写入操作(页面向下约 4/5)以获取清理后的 XML。

以上假设您正在传递一个字符串,您必须使用 parse 从文件输入,例如:

import xml.etree.ElementTree as ET
tree = ET.parse('country_data.xml')
root = tree.getroot()

** 免责声明 *** 我正在做类似的工作,但我实际上并没有尝试过这样做。因此,将此视为灵感,而不是完整的解决方案。

顺便说一句,我使用的是 python 3.7.4。对于那些不知道的人,您可以使用文档页面左上方的版本选择器来选择您正在使用的版本。


推荐阅读