I want to replace child elements from one tree to another , based on some criteria. I can do this using Comprehension ? But how do we replace element in ElementTree?
You can't replace an element from the ElementTree
you can only work with Element
.
Even when you call ElementTree.find()
it's just a shortcut for getroot().find()
.
So you really need to:
- extract the parent element
- use comprehension (or whatever you like) on that parent element
The extraction of the parent element can be easy if your target is a root sub-element (just call getroot()
) otherwise you'll have to find it.
You can't replace an element from the ElementTree
you can only work with Element
.
Even when you call ElementTree.find()
it's just a shortcut for getroot().find()
.
So you really need to:
- extract the parent element
- use comprehension (or whatever you like) on that parent element
The extraction of the parent element can be easy if your target is a root sub-element (just call getroot()
) otherwise you'll have to find it.
I'm new to python, but I've found a dodgy way to do this:
Input file input1.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<import ref="input2.xml" />
<name awesome="true">Chuck</name>
</root>
Input file input2.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar>blah blah</bar>
</foo>
Python code: (note, messy and hacky)
import os
import xml.etree.ElementTree as ElementTree
def getElementTree(xmlFile):
print "-- Processing file: '%s' in: '%s'" %(xmlFile, os.getcwd())
xmlFH = open(xmlFile, 'r')
xmlStr = xmlFH.read()
et = ElementTree.fromstring(xmlStr)
parent_map = dict((c, p) for p in et.getiterator() for c in p)
# ref: https://mcmap.net/q/234774/-access-elementtree-node-parent-node/2170994
importList = et.findall('.//import[@ref]')
for importPlaceholder in importList:
old_dir = os.getcwd()
new_dir = os.path.dirname(importPlaceholder.attrib['ref'])
shallPushd = os.path.exists(new_dir)
if shallPushd:
print " pushd: %s" %(new_dir)
os.chdir(new_dir) # pushd (for relative linking)
# Recursing to import element from file reference
importedElement = getElementTree(os.path.basename(importPlaceholder.attrib['ref']))
# element replacement
parent = parent_map[importPlaceholder]
index = parent._children.index(importPlaceholder)
parent._children[index] = importedElement
if shallPushd:
print " popd: %s" %(old_dir)
os.chdir(old_dir) # popd
return et
xmlET = getElementTree("input1.xml")
print ElementTree.tostring(xmlET)
gives the output:
-- Processing file: 'input1.xml' in: 'C:\temp\testing'
-- Processing file: 'input2.xml' in: 'C:\temp\testing'
<root>
<foo>
<bar>blah blah</bar>
</foo><name awesome="true">Chuck</name>
</root>
this was concluded with information from:
Yes! Using the slice syntax you can do it with comprehension. Ex:
import xml.etree.ElementTree as etree
path = r'C:\Users\XXX\myfile.xml'
tree = etree.parse(path)
root = tree.getroot()
root[:] = [child for child in root if child.get('some-attribute') == 'something']
tree.write(f'{path}.filtered.xml')
© 2022 - 2025 — McMap. All rights reserved.