簡體   English   中英

Python ElementTree

[英]Python ElementTree

我有一個具有以下格式的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>

我該如何實現?

注意使用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 Elements時)。

因此,使用這個想法,我們可以將這些元素收集到新的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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM