python - lxml.etree._Element.append() from a loop not working as expected -


i know why in code append() seems work inside loop, resulting xml displays modification last iteration, while remove() works expected. overly simplified example, i'm working big chunks of data, , need append same subtree many different parents.

from lxml import etree  xml = etree.fromstring('<tree><fruit id="1"></fruit><fruit id="2"></fruit></tree>') sub = etree.fromstring('<apple/>')  i, item in enumerate(xml):     item.append(sub)     print('fruit {} sub appended: {}'.format(         i, etree.tostring(item).decode('ascii')))  print('\nresulting tree after iterating through items append():\n' +     etree.tostring(xml, pretty_print=true).decode('ascii'))  item in xml:     xml.remove(item)  print('resulting tree after iterating through items remove():\n' +     etree.tostring(xml, pretty_print=true).decode('ascii')) 

current output:

fruit 0 sub appended: <fruit id="1"><apple/></fruit> fruit 1 sub appended: <fruit id="2"><apple/></fruit>  resulting tree after iterating through items append(): <tree>   <fruit id="1"/>   <fruit id="2">     <apple/>   </fruit> </tree>  resulting tree after iterating through items remove(): <tree/> 

expected output after iterating through items append():

<tree>   <fruit id="1"/>     <apple/>   </fruit>   <fruit id="2">     <apple/>   </fruit> </tree> 

that's because created one instance of <apple/> appended. moved 1 instance 1 parent until last append(sub) executed. try move creation of <apple/> element within for loop instead :

for i, item in enumerate(xml):     sub = etree.fromstring('<apple/>')     item.append(sub)     print('fruit {} sub appended: {}'.format(         i, etree.tostring(item).decode('ascii'))) print() 

output :

resulting tree after iterating through items append(): <tree>   <fruit id="1">     <apple/>   </fruit>   <fruit id="2">     <apple/>   </fruit> </tree> 

Comments