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

坚强是说给别人听的谎言 提交于 2019-12-20 02:24:26

问题


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>

回答1:


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>


来源:https://stackoverflow.com/questions/31527392/lxml-etree-element-append-from-a-loop-not-working-as-expected

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!