Python 向lxml中的几个子元素添加相同的元素
背景:我试图用从web服务端点检索的元数据充实XML报告。报告列出了文本模块和图形,每个图形都有几个分辨率。我无法为每个解决方案添加元数据 问题:问题简化了Python 向lxml中的几个子元素添加相同的元素,python,lxml,Python,Lxml,背景:我试图用从web服务端点检索的元数据充实XML报告。报告列出了文本模块和图形,每个图形都有几个分辨率。我无法为每个解决方案添加元数据 问题:问题简化了 from lxml import etree as ET myxml = """\ <report> <object id="foo"> <reportitems> <reportitem id="1"/> <re
from lxml import etree as ET
myxml = """\
<report>
<object id="foo">
<reportitems>
<reportitem id="1"/>
<reportitem id="2"/>
<reportitem id="3"/>
</reportitems>
</object>
</report>
"""
report = ET.fromstring(myxml)
test = ET.Element("test", foo="bar")
for r in report.findall("object/reportitems/reportitem"):
r.append(test)
…然后我得到这个输出:
<report>
<object id="foo">
<reportitems>
<reportitem id="1"/>
<reportitem id="2"/>
<reportitem id="3"><test foo="bar"/></reportitem>
</reportitems>
</object>
</report>
<report>
<object id="foo">
<reportitems>
<reportitem id="1"><test1/></reportitem>
<reportitem id="2"><test2/></reportitem>
<reportitem id="3"><test3/></reportitem>
</reportitems>
</object>
</report>
为什么我不能将与子元素相同的元素添加到我迭代的许多元素中?构造函数ET中的问题。它的元素每次调用只创建一个节点。您可以更改节点的父节点,但ET.元素将仅为一个。您可以在循环中多次创建ET.元素以避免此问题:
for r in report.findall("object/reportitems/reportitem"):
node = ET.Element("test", foo="bar")
r.append(node)
此行为在以下章节中描述: 还有另一个重要的情况,即 2.0及更高版本中的lxml与列表和 版本1.3或Python 2.7/3.2之前的原始ElementTree: 在本例中,最后一个元素移动到不同的位置, 而不是被复制,即自动从其 放置在不同位置时的上一个位置。在列表中, 对象可以同时出现在多个位置,并且 上面的赋值只是将项目引用复制到第一个 位置,以便两者包含完全相同的项目: 请注意,在原始ElementTree中,单个元素对象可以位于任意数量树中的任意位置, 允许与列表相同的复制操作。显而易见的 缺点是对此类元素的修改将适用于所有 它出现在树上的地方,可能是有意的,也可能不是有意的。 这种差异的好处是lxml.etree中的元素总是 只有一个父级,可以通过getparent查询 方法这在原始ElementTree中不受支持 如果要将元素复制到LXML.ETRE中的不同位置,请考虑 使用Python的复制模块创建独立的深度复制 标准库:
预期产量是多少?目前,您没有传递相同的元素:test1!=我所期望的是能够将相同的元素作为子元素添加到id分别为1、2和3的每个元素中。我添加了修改后的脚本,它成功地添加了不同的子元素,作为一个重要的元素?对比。是的,但我想OP会问为什么?试图在文档或源代码中找到实际的解释。。
for r in report.findall("object/reportitems/reportitem"):
node = ET.Element("test", foo="bar")
r.append(node)
>>> for child in root:
... print(child.tag)
child0 child1 child2 child3
>>> root[0] = root[-1] # this moves the element in lxml.etree!
>>> for child in root:
... print(child.tag)
child3 child1 child2
>>> l = [0, 1, 2, 3]
>>> l[0] = l[-1]
>>> l
[3, 1, 2, 3]
>>> root is root[0].getparent() # lxml.etree only!
True
>>> from copy import deepcopy
>>> element = etree.Element("neu")
>>> element.append( deepcopy(root[1]) )
>>> print(element[0].tag)
child1
>>> print([ c.tag for c in root ])
['child3', 'child1', 'child2']