xml - 如何使用 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>
展望未来,我要输入删除的不是单个值,而是数千个值,所以要成为一个列表,我只是认为以这种方式表示问题更容易。任何帮助表示赞赏。
解决方案
由于您的 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。对于那些不知道的人,您可以使用文档页面左上方的版本选择器来选择您正在使用的版本。
推荐阅读
- angular - 为什么轮播代码不起作用?
- python - 按主机名路由数据库
- ionic-framework - 如何修复此错误 [错误:无法找到 '@ionic/angular/css/display.css']
- javascript - react脚本和jest版本24.7.1冲突
- header - 接受 wiki api 请求的标题中的配置文件是什么
- git - git clone 后在 Intellij 中标记为非项目文件的所有文件
- excel - 是否有一个 Excel 函数(/方法)用于基于两列与 vlookup 属性进行近似匹配的文本?
- python - Python:匹配列表中的元素
- azure - 是否可以从 Azure 数据工厂中的表中更新行值?
- vb.net - Contains() 语句没有找到指示的字符串