我试图删除整个元素时,它包含某些子元素。我弄清楚了如何和我的代码在小样本文件上工作得很好,但是当我在大文件(超过20Mb)上尝试它时,它只删除了一些元素。如果我在结果上重复运行代码,由于某种原因,它在几次运行后删除了我在第一次运行时期望的所有元素,我猜这只是随机的运气,代码没有在第一时间给出异常或一些错误。
XML示例:
<root>
<element1>
<sub1>
<subsub1>
</subsub1>
</sub1>
<sub2>
<subsub2>
<foo STyp="foo">
<bar>
</bar>
</foo>
</subsub2>
</sub2>
</element1>
</root>
如果包含<foo STyp="foo"></foo>
,我想删除整个element1。
代码:
import xml.etree.ElementTree as ET
tree = ET.parse("my.xml")
for root in tree.iter():
for element1 in root:
el = element1.find('foo')
if el is not None:
root.remove(element1)
tree.write('1.xml')
我很困惑它能在更小的文件上工作
fromElement.iter()
documentation:
如果在迭代过程中修改了树结构,则结果未定义。
你的问题是你在修改树的同时迭代它的元素。您可以使用XPath来查找所需元素的祖父母元素。然后在其中找到它们的父元素,并从祖父元素中删除父元素。(因为python XML不允许你直接访问父节点)
for grandparent_of_foo in root.findall(".//foo[@STyp='foo']/../../."):
for parent_of_foo in grandparent_of_foo.findall("*/foo[@STyp='foo']/../."):
grandparent_of_foo.remove(parent_of_foo)
对于这个输入:
<root>
<element1>
<sub1>
<subsub1>
<subsub4>
<foo STyp="foo">
</foo>
</subsub4>
</subsub1>
</sub1>
<sub2>
<subsub2>
<foo STyp="foo">
<bar>
</bar>
</foo>
</subsub2>
<subsub3>
<bar>
</bar>
</subsub3>
</sub2>
</element1>
</root>
打印root
节点将产生以下结果:
print(ET.tostring(root, encoding='utf-8').decode())
<root>
<element1>
<sub1>
<subsub1>
</subsub1>
</sub1>
<sub2>
<subsub3>
<bar>
</bar>
</subsub3>
</sub2>
</element1>
</root>
您可以在这里查看Xpath语法。