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?

4
  • 1
    Did you run that code? What were the results? Commented Jul 31, 2014 at 20:58
  • 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. Commented Jul 31, 2014 at 21:12
  • 1
    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. Commented Jul 31, 2014 at 21:15
  • Alright captain! Will keep that in mind. Commented Jul 31, 2014 at 21:18

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

7 Comments

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.
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..
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!
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?
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)
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.