Modify a XML using ElementTree
Asked Answered
P

1

7
<grandParent>
    <parent>
       <child>Sam/Astronaut</child>
    </parent>
</grandParent>

I want to modify the above XML by adding another child tag inside parent tag. I'm doing something like this..

tree = ET.parse("test.xml")
a=ET.Element('parent')
b=ET.SubElement(a,"child")
b.text="Jay/Doctor"
tree.write("test.xml")

Is this the correct way of modifying the xml file? Any better way? or what else should I be taking care of in the above code?

Passe answered 31/7, 2014 at 20:46 Comment(4)
Did you run that code? What were the results?Clint
When I run this code now, I don't see the XML getting modified. I thought I did see it getting modified earlier and I had received the results required but thought its not correct way hence posted.Passe
When you ask questions on SO, it is good to include all the relevant information, including the expected and observed results of whatever code you post. Otherwise, good question.Clint
Alright captain! Will keep that in mind.Passe
A
10

Your code creates a whole new tree and adds Jay to it. You need to connect Jay to the existing tree, not to a new one.

Try this:

import xml.etree.ElementTree as ET

tree = ET.parse("test.xml")
a = tree.find('parent')          # Get parent node from EXISTING tree
b = ET.SubElement(a,"child")
b.text = "Jay/Doctor"
tree.write("test.xml")

If you want to search for a particular child, you could do this:

import xml.etree.ElementTree as ET
tree = ET.parse("test.xml")
a = tree.find('parent')
for b in a.findall('child'):
    if b.text.strip() == 'Jay/Doctor':
        break
else:
    ET.SubElement(a,"child").text="Jay/Doctor"
tree.write("test.xml")

Notice a.findall() (similar to a.find(), but returns all of the named elements). xml.etree has very limited search criteria. You might consider using lxml.etree and its .xpath() method.

Aleshia answered 31/7, 2014 at 20:55 Comment(7)
thanks this works.I think I could use find() to verify no child similar to one I am about to enter exists. To avoid duplicates.Passe
actually, how do I execute the find command inside the parent tag? Two parent tags could have same children but a single parent should not have duplicates..Passe
that worked for me. This might be all I need from ElementTree. I will look into lxml.etree if I need more capability I guess. Thanks much!Passe
Well I guess I spoke too soon - I am now having name spaces in the parent tag and my find all method now has a problem ... AttributeError: 'NoneType' object has no attribute 'findall' How do I handle this?Passe
I am doing something like this. spaces={'xmlns':'maven.apache.org/POM/4.0.0', 'xsi':'w3.org/2001/XMLSchema-instance', 'schemaLocation':'maven.apache.org/xsd/maven-4.0.0.xsd'} using spaces in the find all method.. find all('module', namespaces=spaces)Passe
That sounds like a new question.Clint
Here it is: #25070680Passe

© 2022 - 2024 — McMap. All rights reserved.