我必须创建一个XML文档,该文档必须具有在不同部分重复的相同信息。我正在创建一些details
作为etree.Element并将其附加到几个辅助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))
我想要的输出是;
<Primary>
<Secondary>
<Details somevalue="value"/>
</Secondary>
<Secondary>
<Details somevalue="value"/>
</Secondary>
</Primary>
我得到的输出是;
<Primary>
<Secondary/>
<Secondary>
<Details somevalue="value"/>
</Secondary>
</Primary>
lxml似乎只将details
元素放在一个位置。有什么办法可以关闭它吗?
谢谢!
答案 0 :(得分:2)
以下内容摘自lxml documentation
请注意,在原始ElementTree中,可以放置一个Element对象 在任何数量的树木中的任何数量的地方,这允许 与列表相同的复制操作。明显的缺点是 对此类元素的修改将应用于该元素的所有位置 出现在树上,这可能是预期的,也可能不是预期的。
这种区别的好处是lxml.etree中的Element总是 仅有一个父对象,可以通过getparent()查询 方法。原始ElementTree不支持此功能。
因此,与ElementTree中的原始元素不同,lxml中的一个元素只能具有一个父元素。因此,不可能仅使用lxml将同一元素附加到多个父对象。但是,文档建议处理这种新设计,如果已将其分配给其他元素,则应使用深层复制将要附加的元素复制到另一个元素。
这将创建该元素的新副本,因此可以将该新副本分配给其他父元素。这些是单独的副本,因此更改一个不会更改另一个。
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))
输出
<Primary>
<Secondary>
<Details somevalue="value"/>
</Secondary>
<Secondary>
<Details somevalue="value"/>
</Secondary>
</Primary>
已更新杰克示例
因此,在杰克的示例中,我设置了一个变量num_secondarys
,该变量将创建X个次要元素,每个元素都包含一个detail元素,并且detail元素中的值将增加1。模板,然后使用Deepcopy将其复制为新元素。
from lxml import etree
from copy import deepcopy
top = etree.Element('Primary')
secondary = etree.Element('Secondary')
detail = etree.Element('Details', somevalue='value')
num_secondarys = 3
for i in range(1, num_secondarys + 1):
this_secondary = deepcopy(secondary)
this_detail = deepcopy(detail)
this_detail.attrib['somevalue']+=str(i)
this_secondary.append(this_detail)
top.append(this_secondary)
print(etree.tostring(top, encoding="unicode", pretty_print=True))
输出
<Primary>
<Secondary>
<Details somevalue="value1"/>
</Secondary>
<Secondary>
<Details somevalue="value2"/>
</Secondary>
<Secondary>
<Details somevalue="value3"/>
</Secondary>
</Primary>
答案 1 :(得分:0)
下面(使用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)
输出
<Primary>
<Secondary>
<Details somevalue="value" />
</Secondary>
<Secondary>
<Details somevalue="value" />
</Secondary>
</Primary>