循环中的lxml.etree._Element.append()无法按预期工作

3
我想知道为什么在这段代码中,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>

同样,这在xml.etree.ElementTree中也可以工作,不像lxml。 - stunlocked
1个回答

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

output :

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

可以,谢谢!为什么 print('Fruit {} with sub appended: {}'... 能够输出正确的结果?我是 Python 的新手,所以这是我还不理解的一些概念! - admirabilis
1
好的,它实际上修改了每个项目,但是稍后<apple/>被删除了,现在我明白了!谢谢! - admirabilis
有没有办法在每次迭代时不从字符串中读取XML?我的子程序已经是etree格式了。 - stunlocked
修正了代码中的 i.append(ET.fromstring(ET.tostring(sub))) - stunlocked

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接