1

My XML:

<animals>
  <animal name="fox" fullname="fullfox"></animal>
  <animal name="dog" fullname="halfdog"><food>milk</food><food>rice</food><food>meat</food>   </animal>
  <animal name="cow" fullname="doublecow"><food>grass</food></animal>
  <animal name="blabla" fullname="fullbla"></animal>
</animals>

I'm trying to parse this XML to get same XML as output.

doc    = ET.parse("an.xml")
root = doc.getroot() #Returns the root element for this tree.
root_new  = ET.Element("animals") 
for child in root:
    name = child.attrib['name']
    fullname = child.attrib['fullname']

for g in root.findall("*/food"):
    animal    = ET.SubElement(root_new, "animal") 
    food     = ET.SubElement(animal, "food")   
    food.text = g.text
    animal.set("name",name)               
    animal.set("fullname",fullname) 

tree = ET.ElementTree(root_new)
tree.write(sys.stdout)

But am getting only last value

<animals>
  <animal fullname="fullbla" name="blabla"><food>milk</food></animal>
  <animal fullname="fullbla" name="blabla"><food>rice</food></animal>
  <animal fullname="fullbla" name="blabla"><food>meat</food></animal>
  <animal fullname="fullbla" name="blabla"><food>grass</food></animal>
</animals>

And food node also wrong, how to iterate exactly like my input XML?

3
  • You should group together the food tags that are children of an object. Try to iterate over the animals and for each animal iterate over the foods. Commented Nov 5, 2012 at 8:21
  • i try that way tooo..but same :( Commented Nov 5, 2012 at 8:23
  • But no one can answer exactly , the output xml indendation :( , all xml here, which i accepted also coming in one line :( Commented Nov 5, 2012 at 8:42

3 Answers 3

2

your code should look like this

doc    = ET.parse("test.xml")
root = doc.getroot() #Returns the root element for this tree.
root_new  = ET.Element("animals") 
for child in root:
    name             = child.attrib['name']
    fullname         = child.attrib['fullname']
    animal    = ET.SubElement(root_new, "animal") 
    animal.set("name",name)               
    animal.set("fullname",fullname) 

    for g in child.findall("food"):
        food = ET.SubElement(animal, "food")   
        food.text = g.text

tree = ET.ElementTree(root_new)
tree.write(sys.stdout)
Sign up to request clarification or add additional context in comments.

Comments

2

You need a nested loop:

for child in root:
    name             = child.attrib['name']
    fullname         = child.attrib['fullname']
    # create "animal" here
    animal    = ET.SubElement(root_new, "animal") 
    animal.set("name",name)               
    animal.set("fullname",fullname)
    for g in child.findall("food"):
        # create "food" here
        food     = ET.SubElement(animal, "food")   
        food.text = g.text 

1 Comment

<animals><animal fullname="fullfox" name="fox" /><animal fullname="halfdog" name="dog" /><animal fullname="doublecow" name="cow" /><animal fullname="fullbla" name="blabla" /></animals> : this is out put...hmmm wrong one bro :(
1

There are two problems. The first is your indentation - I assume those are meant to be nested loops. The second problem is that you're using root.findall, which means that you are getting all food items regardless of which node they are in. Try this instead:

...
for child in root:
    name = child.attrib['name']
    fullname = child.attrib['fullname']
    animal = ET.SubElement(root_new, 'animal')
    for g in child.findall("food"):
        food = ET.SubElement(animal, "food")   
        food.text = g.text
        animal.set('name', name)               
        animal.set('fullname', fullname) 

2 Comments

animal should be created before the child loop
out put is only this , how u said its working :) : <animals />

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.