How to clone Element
objects in Python xml.etree
? I'm trying to procedurally move and copy (then modify their attributes) nodes.
You can just use copy.deepcopy() to make a copy of the element. (this will also work with lxml by the way).
A different, and somewhat disturbing solution:
new_element = lxml.etree.fromstring(lxml.etree.tostring(elem))
If you have a handle on the Element
elem
's parent
you can call
new_element = SubElement(parent, elem.tag, elem.attrib)
Otherwise you might want to try
new_element = makeelement(elem.tag, elem.attrib)
but this is not advised.
id(old_element)
with id(new_element)
to see if it actually creates a different object in memory. Does this help? –
Messinger Element
and its attributes, but you do not want to copy the children (for example when reconstructing a strict subtree by iterating through an element's ancestors). It is portable to lxml.etree, because unfortunately with lxml.etree, copy.copy()
also copies children (documented, but how is this different from a deepcopy?). –
Shellashellac At least in Python 2.7 etree Element has a copy method: http://hg.python.org/cpython/file/2.7/Lib/xml/etree/ElementTree.py#l233
It is a shallow copy, but that is preferable in some cases.
In my case I am duplicating some SVG Elements and adding a transform. Duplicating children wouldn't serve any purpose since where relevant they already inherit their parent's transform.
Element.copy()
does not exist in lxml.etree, and copy.copy()
copies children too, when applied to an lxml.etree.Element
. –
Shellashellac If you procedurally move through your tree with loops, you can use insert
to clone directly ( insert(index, subelement)
) and tree indexing (both in the documentation):
import xml.etree.ElementTree as ET
mytree = ET.parse('some_xml_file.xml') # parse tree from xml file
root = mytree.getroot() # get the tree root
for elem in root: # iterate over children of root
if condition_for_cloning(elem) == True:
elem.insert(len(elem), elem[3]) # insert the 4th child of elem to the end of the element (clone an element)
or for children with some tag:
for elem in root:
children_of_interest = elem.findall("tag_of_element_to_clone")
elem.insert(len(elem), children_of_interest[1])
For anyone visiting from the future:
If you want to clone the entire element, use append
.
new_tree = ET.Element('root')
for elem in a_different_tree:
new_tree.append(elem)
@dennis-williamson made a comment about it which I overlooked and eventually stumbled on the answer here https://mcmap.net/q/340005/-can-39-t-dump-or-write-an-elementtree-element
For future reference.
Simplest way to copy a node (or tree) and keep it's children, without having to import ANOTHER library ONLY for that:
def copy_tree( tree_root ):
return et.ElementTree( tree_root );
duplicated_node_tree = copy_tree ( node ); # type(duplicated_node_tree) is ElementTree
duplicated_tree_root_element = new_tree.getroot(); # type(duplicated_tree_root_element) is Element
© 2022 - 2024 — McMap. All rights reserved.
append()
orinsert()
to do that. – Aitken