来自循环的lxml.etree._Element.append()不能按预期工作

时间:2015-07-20 22:28:25

标签: python lxml

我想知道为什么在这个代码中append()似乎在循环内部起作用,但是生成的xml仅显示最后一次迭代的修改,而remove()按预期工作。这是一个过于简化的例子,我处理大块数据,需要将相同的子树附加到许多不同的父节点。

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'))

当前输出:

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/>

在使用append() 的项目进行迭代后,的预期输出:

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

1 个答案:

答案 0 :(得分:1)

那是因为你只创建了一个<apple/>的实例来追加。所以基本上你只是将一个实例从一个父实例移动到另一个实例,直到最后append(sub)执行。尝试在<apple/>循环中移动创建for元素:

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()

输出

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