Следующее извлечено из документации lxml
Обратите внимание, что в исходном ElementTree один объект Element может находиться в любом количестве мест в любом количестве деревьев,которая допускает ту же операцию копирования, что и со списками. Очевидным недостатком является то, что изменения такого элемента будут применяться ко всем местам, где он появляется в дереве, что может или не может быть предназначено.
Преимущество этого различия состоит в том, что элемент в lxml.etree всегдаимеет ровно одного родителя, к которому можно обратиться с помощью метода getparent (). Это не поддерживается в исходном ElementTree.
Таким образом, элемент в lxml может иметь только одного родителя в отличие от исходного элемента из ElementTree. Поэтому невозможно просто добавить один и тот же элемент к нескольким родителям с помощью 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 вторичных элементов, каждый из которых содержит элемент details, а значения в элементе detail будут увеличиваться на 1. Я создаю один элемент Secondary и detail какшаблон, а затем используйте 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))
OUTPUT
<Primary>
<Secondary>
<Details somevalue="value1"/>
</Secondary>
<Secondary>
<Details somevalue="value2"/>
</Secondary>
<Secondary>
<Details somevalue="value3"/>
</Secondary>
</Primary>