Reputation: 2420
I would like to know why in this code append()
seems to work from inside the loop, but the resulting xml displays the modification from only the last iteration, while remove()
works as expected. This is a overly simplified example, I'm working with big chunks of data, and need to append the same subtree to many different parents.
from lxml import etree
xml = etree.fromstring('<tree><fruit id="1"></fruit><fruit id="2"></fruit></tree>')
sub = etree.fromstring('<apple/>')
for i, item in enumerate(xml):
item.append(sub)
print('Fruit {} with sub appended: {}'.format(
i, etree.tostring(item).decode('ascii')))
print('\nResulting tree after iterating through items with append():\n' +
etree.tostring(xml, pretty_print=True).decode('ascii'))
for item in xml:
xml.remove(item)
print('Resulting tree after iterating through items with remove():\n' +
etree.tostring(xml, pretty_print=True).decode('ascii'))
Current output:
Fruit 0 with sub appended: <fruit id="1"><apple/></fruit>
Fruit 1 with sub appended: <fruit id="2"><apple/></fruit>
Resulting tree after iterating through items with append():
<tree>
<fruit id="1"/>
<fruit id="2">
<apple/>
</fruit>
</tree>
Resulting tree after iterating through items with remove():
<tree/>
Expected output from after iterating through items with append()
:
<tree>
<fruit id="1"/>
<apple/>
</fruit>
<fruit id="2">
<apple/>
</fruit>
</tree>
Upvotes: 3
Views: 1216
Reputation: 89295
That's because you only created one instance of <apple/>
to be appended. So basically you just moved that one instance from one parent to another until the last append(sub)
executed. Try to move creation of the <apple/>
element within for
loop instead :
for i, item in enumerate(xml):
sub = etree.fromstring('<apple/>')
item.append(sub)
print('Fruit {} with sub appended: {}'.format(
i, etree.tostring(item).decode('ascii')))
print()
output :
Resulting tree after iterating through items with append():
<tree>
<fruit id="1">
<apple/>
</fruit>
<fruit id="2">
<apple/>
</fruit>
</tree>
Upvotes: 1