我有一个XML文件,格式如下:
<dir name="A">
<dir name="B">
<file name="foo.txt"/>
</dir>
<dir name="C">
<dir name="D">
<file name="bar.txt"/>
</dir>
</dir>
</dir>
<dir name="E">
<file name="bat.txt"/>
<file name="cat.txt"/>
</dir>
<dir name="F">
<dir name="G">
<file name="dog.txt"/>
<file name="rabbit.txt"/>
</dir>
</dir>我想使用python ElementTree模块来删除任何包含元素的元素。也就是说,我希望获得XML文件的内部元素(其中不包含另一个元素的元素),以及它们的所有子元素。我希望将任何这样的元素设置为外层。例如,对于上面的XML文件,对应的输出文件为:
<dir name="B">
<file name="foo.txt"/>
</dir>
<dir name="D">
<file name="bar.txt"/>
</dir>
<dir name="E">
<file name="bat.txt"/>
<file name="cat.txt"/>
</dir>
<dir name="G">
<file name="dog.txt"/>
<file name="rabbit.txt"/>
</dir>我如何才能做到这一点?
发布于 2014-10-06 06:01:15
注意use iterparse时访问元素的顺序--这是深度优先搜索:
import xml.etree.ElementTree as ET
with open('data', 'rb') as f:
context = ET.iterparse(f, events=('start', 'end'))
for event, elem in context:
if elem.tag == 'dir':
name = elem.get('name')
print(event, name)收益率
('start', 'A')
('start', 'B') <-- ('start', 'B') is follow immediately by ('end', 'B')
('end', 'B') <--
('start', 'C')
('start', 'D') <-- start is follow immediately by end
('end', 'D')
('end', 'C')
('end', 'A')
('start', 'E') <-- start is follow immediately by end
('end', 'E')
('start', 'F')
('start', 'G') <-- start is follow immediately by end
('end', 'G')
('end', 'F')啊哈,您正在寻找的元素--嵌套最深的dir元素--是那些iterparse首先使用start事件访问,然后紧接着使用end事件访问的元素(至少当我们只查看dir元素时是这样的)。
因此,使用这个想法,我们可以将这些元素收集到一个新的root元素中,以获得所需的XML:
root = ET.Element('root')
previous_name = None
with open('data', 'rb') as f:
context = ET.iterparse(f, events=('start', 'end'))
for event, elem in context:
if elem.tag == 'dir':
name = elem.get('name')
if event == 'start':
previous_name = name
elif previous_name == name:
root.append(elem)
print(ET.tostring(root))收益率
<root><dir name="B">
<file name="foo.txt" />
</dir>
<dir name="D">
<file name="bar.txt" />
</dir>
<dir name="E">
<file name="bat.txt" />
<file name="cat.txt" />
</dir>
<dir name="G">
<file name="dog.txt" />
<file name="rabbit.txt" />
</dir>
</root>注意,在iterparse访问任何元素之后,上面的iterparse代码不会清除任何元素。如果XML很大,在不清除任何元素的情况下使用iterparse可能会占用太多内存。在这种情况下,为了性能和更好的内存管理,我会使用lxml和fast_iter。
https://stackoverflow.com/questions/26207372
复制相似问题