這似乎取決於您是使用內置的ElementTree還是lxml。
隨着LXML,你應該能夠使用copy
:
from lxml import etree
e = etree.Element('root')
etree.SubElement(e, 'child1')
etree.SubElement(e, 'child2')
from copy import copy
f = copy(e)
f[0].tag = 'newchild1'
etree.dump(e)
<root>
<child1/>
<child2/>
</root>
etree.dump(f)
<root>
<newchild1/>
<child2/>
</root>
你可以看到,新的樹實際上是從舊的分離;這是因爲lxml將父元素存儲在元素中,因此不能重用它們 - 必須爲每個子元素創建新元素。
ElementTree不會將元素保留在元素中,因此同一元素可能同時在多個樹中共存。據我所知,沒有內置的方法來強制進行深度複製... deepcopy
和element.copy()
兩者的作用與copy
完全相同 - 它們複製節點,但將其從原始節點連接到子節點。所以對副本的更改會改變原來的 - 不是你想要的。
我發現使它正常工作的最簡單方法是簡單地序列化爲一個字符串,然後再反序列化它。這迫使全新的元素被創建。這很慢 - 但它也一直有效。比較下列方法:
import xml.etree.ElementTree as etree
e = Element('root')
etree.SubElement(e, 'child1')
etree.SubElement(e, 'child2')
#f = copy(e)
#f[0].tag = 'newchild1'
# If you do the above, the first child of e will also be 'newchild1'
# So that won't work.
# Simple method, slow but complete
In [194]: %timeit f = etree.fromstring(etree.tostring(e))
10000 loops, best of 3: 71.8 µs per loop
# Faster method, but you must implement the recursion - this only
# looks at a single level.
In [195]: %%timeit
.....: f = etree.Element('newparent')
.....: f.extend([x.copy() for x in e])
.....:
100000 loops, best of 3: 9.49 µs per loop
這個底部方法確實創建了一級子級的副本,比第一個版本快很多。但是,這隻適用於單層嵌套;如果其中任何一個有孩子,那麼你必須自己下載並複製這些內容。您可能可以編寫遞歸副本,而且速度可能更快;我做過這些的地方沒有對性能敏感,所以我沒有在我的代碼中感到困擾。 tostring/fromstring例程的效率相當低,但卻很直接,並且無論樹有多深,它都可以正常工作。
但我怎麼能做出選擇只考慮duplicateAndAddOne? – Nickpick
你必須遍歷每個元素,並提取'name'元素,然後決定如何處理它。儘管如果你能夠控制這個XML,那麼'Strategy'似乎不適用於該部分;類似於'strategy ='duplicate''屬性的'DataFrame'似乎在語義上更一致... –