简体   繁体   English

使用 lxml 重复 XML 元素

[英]Repeating XML elements using lxml

I've got to create an XML document which has to have the same information repeated in different parts.我必须创建一个 XML 文档,该文档必须在不同部分重复相同的信息。 I'm creating some details as an etree.Element and trying to append it to a couple of secondary XML elements我正在创建一些details作为 etree.Element 并尝试将 append 它添加到几个辅助 XML 元素

from lxml import etree

top = etree.Element('Primary')
element1 = etree.Element('Secondary')
element2 = etree.Element('Secondary')

details = etree.Element('Details', somevalue='value')

element1.append(details)
element2.append(details)
top.append(element1)
top.append(element2)

print(etree.tostring(top, encoding="unicode", pretty_print=True))

The output I want is;我想要的 output 是;

<Primary>
  <Secondary>
    <Details somevalue="value"/>
  </Secondary>
  <Secondary>
    <Details somevalue="value"/>
  </Secondary>
</Primary>

The output I get is;我得到的 output 是;

<Primary>
  <Secondary/>
  <Secondary>
    <Details somevalue="value"/>
  </Secondary>
</Primary>

lxml seems to treat the details element only being allowed in one place. lxml 似乎只在一个地方允许details元素。 Is there any way to turn this off?有什么办法可以关闭它吗?

Thanks!谢谢!

The following is extracted from the lxml documentation以下内容摘自lxml 文档

Note that in the original ElementTree, a single Element object can sit in any number of places in any number of trees, which allows for the same copy operation as with lists.请注意,在原始 ElementTree 中,单个元素 object 可以位于任意数量的树中的任意数量的位置,这允许与列表相同的复制操作。 The obvious drawback is that modifications to such an Element will apply to all places where it appears in a tree, which may or may not be intended.明显的缺点是对此类元素的修改将应用于它出现在树中的所有位置,这可能是也可能不是有意的。

The upside of this difference is that an Element in lxml.etree always has exactly one parent, which can be queried through the getparent() method.这种差异的好处是 lxml.etree 中的 Element 总是只有一个父级,可以通过 getparent() 方法查询。 This is not supported in the original ElementTree.这在原始 ElementTree 中不受支持。

So an element in lxml can only have one parent unlike the original element from ElementTree.因此,与 ElementTree 中的原始元素不同,lxml 中的元素只能有一个父元素。 So its not possible to just append the same element to more than one parent using lxml.因此,使用 lxml 不可能只将 append 相同的元素传递给多个父级。 However the documentation suggests to handle this new design you should use deep copy to copy the element you want to append to another element if its already assigned somewhere.然而,文档建议处理这个新设计,你应该使用深拷贝将你想要的元素复制到 append 到另一个元素,如果它已经分配到某个地方。

This will create a new copy of the element and as such the new copy can be assigned to a different parent element.这将创建元素的新副本,因此可以将新副本分配给不同的父元素。 These are seperate copy's so changing one will not change the other.这些是单独的副本,因此更改一个不会更改另一个。

from lxml import etree
from copy import deepcopy

top = etree.Element('Primary')
element1 = etree.Element('Secondary')
element2 = etree.Element('Secondary')
details = etree.Element('Details', somevalue='value')
element1.append(details)
element2.append(deepcopy(details))
top.append(element1)
top.append(element2)
print(etree.tostring(top, encoding="unicode", pretty_print=True))

OUTPUT OUTPUT

<Primary>
  <Secondary>
    <Details somevalue="value"/>
  </Secondary>
  <Secondary>
    <Details somevalue="value"/>
  </Secondary>
</Primary>

Below (using ElementTree the builtin python XML library)下面(使用 ElementTree 内置的 python XML 库)

import xml.etree.ElementTree as ET

root = ET.Element('Primary')
for x in range(2):
  sec = ET.SubElement(root, 'Secondary')
  details = ET.Element('Details')
  details.attrib['somevalue'] = 'value'
  sec.append(details)
ET.dump(root)

output output

<Primary>
   <Secondary>
      <Details somevalue="value" />
   </Secondary>
   <Secondary>
      <Details somevalue="value" />
   </Secondary>
</Primary>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM