0

I have the following XML structure:

<celestialBodies>
<stars>
    <star>
        <item name="Name">Sun</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </star>
</stars>
<planets>  
    <planet>
        <item name="Name">Mercury</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Venus</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Earth</item>
        <item name="Distance from the Earth">0</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Mars</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Jupiter</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Saturn</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Uranus</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Neptune</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Pluto</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
</planets>  
</celestialBodies>

and I would like to read each of these into a created object in Python 3.

I have the following loop:

# Create the solar system
celestialBodies = list()
for i in range(10):
    planet = Planet("Mercury", 1000000, 0.5, 0.1, ['Moon A', 'Moon B'], ['Hydrogen, Nitrogen'], 8, 0.15)
    celestialBodies.append(planet)

but as you can see, instead of hardcoding the planets myself, I would like to get the data from the XML file in a nice way. So instead of me saying "Mercury", it should traverse through the tree and get the values of each celestial body into the variables and create the object.

What I can't get it through is the XML reading part. No matter what I tried I could not loop through the levels to read the values into the variables. I've already tried BeautifulSoup, lxml, ET but no luck.

Some trials:

   root = lxml.etree.fromstring('planet_info.xml')
   results = root.findall('planets')
   textnumbers = [r.find('planet/name').text for r in results]
   print(textnumbers)

or

solarSystem = ET.parse('planet_info.xml')
celestialBodies = solarSystem.getroot()
for bodies in celestialBodies:
    for star in bodies[0]:
        print(star.tag, star.attrib, star.nodeValue)

with each resulting with errors. There should be a straightforward way of doing this.

Any suggestions?

EDIT: So with the following I am able to reach the two children but no more:

   # Get the data from the XML
   solarSystem = ET.parse('planet_info.xml')
   celestialBodies = solarSystem.getroot()
   for bodies in celestialBodies:
       print(bodies.tag, bodies.attrib)

output:

stars {}
planets {}

How to loop inside these and retrieve the values though?

1
  • Your XML structure could exploit the possibilities of the format better than using just one universal item element. Commented Aug 3, 2018 at 8:22

3 Answers 3

2

Firstly you can find planets and stars elements, add them to list and choose first values from it.

import xml.etree.ElementTree as ET  
dump = ET.parse('planet_info.xml') 
root = dump.getroot()  
planet_name = star_name = planet_list = []  
for content in root:
    planet_name = content.findall("planet")
    star_name = content.findall("star")
    if planet_name:
        for planet in planet_name:
             planet_list.append(Planet(planet[0].text, planet[1].text, etc)
    elif star_name:
        for star in star_name:
            planet_list.append(Planet(star[0].text, star[1].text, etc)
    else:
        print("Nothing")
Sign up to request clarification or add additional context in comments.

Comments

2

This code using etree works. You are missing one line that returns only the item elements which have name set to some value.

import xml.etree.ElementTree as ET

root = ET.parse(PATH_TO_YOUR_FILE)
planets = root.findall('./planets/planet')

planets_list = []
for planet in planets:
        name = planet.find("./item[@name='Name']").text
        d = planet.find("./item[@name='Distance from the Earth']").text
        //...
        planets_list.append(Planet(name, d, ...)

From here you should be able to solve the rest yourself. Hope it helps.

2 Comments

I get the error of AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'name'
which version of etree/python are you using?
0

Here''s a simple way to iterate over that data structure. To keep the code self-contained, I read the XML directly from a string, rather than from a file.

import xml.etree.ElementTree as ET

data = '''\
<?xml version="1.0"?>
<celestialBodies>
<stars>
    <star>
        <item name="Name">Sun</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </star>
</stars>
<planets>  
    <planet>
        <item name="Name">Mercury</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Venus</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Earth</item>
        <item name="Distance from the Earth">0</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Mars</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Jupiter</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Saturn</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Uranus</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Neptune</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
    <planet>
        <item name="Name">Pluto</item>
        <item name="Distance from the Earth">100000</item>
        <item name="Size">9</item>
        <item name="Moons">A,B,C</item>
        <item name="Gravity">0.4</item>
        <item name="Elements Found">H, HE, C</item>
        <item name="Orbiting Time">15</item>
        <item name="Day Time">12</item>
    </planet>
</planets>  
</celestialBodies>
'''

root = ET.fromstring(data)

for kind in root:
    print(kind.tag)
    for child in kind:
        print(' '*2, child.tag)
        for item in child:
            print(' '*4, '{!r}: {!r}'.format(item.attrib['name'], item.text))
        print()

output

stars
   star
     'Name': 'Sun'
     'Distance from the Earth': '100000'
     'Size': '9'
     'Moons': 'A,B,C'
     'Gravity': '0.4'
     'Elements Found': 'H, HE'
     'Orbiting Time': '15'
     'Day Time': '12'

planets
   planet
     'Name': 'Mercury'
     'Distance from the Earth': '100000'
     'Size': '9'
     'Moons': 'A,B,C'
     'Gravity': '0.4'
     'Elements Found': 'H, HE, C'
     'Orbiting Time': '15'
     'Day Time': '12'

   planet
     'Name': 'Venus'
     'Distance from the Earth': '100000'
     'Size': '9'
     'Moons': 'A,B,C'
     'Gravity': '0.4'
     'Elements Found': 'H, HE, C'
     'Orbiting Time': '15'
     'Day Time': '12'

   planet
     'Name': 'Earth'
     'Distance from the Earth': '0'
     'Size': '9'
     'Moons': 'A,B,C'
     'Gravity': '0.4'
     'Elements Found': 'H, HE, C'
     'Orbiting Time': '15'
     'Day Time': '12'

   planet
     'Name': 'Mars'
     'Distance from the Earth': '100000'
     'Size': '9'
     'Moons': 'A,B,C'
     'Gravity': '0.4'
     'Elements Found': 'H, HE, C'
     'Orbiting Time': '15'
     'Day Time': '12'

   planet
     'Name': 'Jupiter'
     'Distance from the Earth': '100000'
     'Size': '9'
     'Moons': 'A,B,C'
     'Gravity': '0.4'
     'Elements Found': 'H, HE, C'
     'Orbiting Time': '15'
     'Day Time': '12'

   planet
     'Name': 'Saturn'
     'Distance from the Earth': '100000'
     'Size': '9'
     'Moons': 'A,B,C'
     'Gravity': '0.4'
     'Elements Found': 'H, HE, C'
     'Orbiting Time': '15'
     'Day Time': '12'

   planet
     'Name': 'Uranus'
     'Distance from the Earth': '100000'
     'Size': '9'
     'Moons': 'A,B,C'
     'Gravity': '0.4'
     'Elements Found': 'H, HE, C'
     'Orbiting Time': '15'
     'Day Time': '12'

   planet
     'Name': 'Neptune'
     'Distance from the Earth': '100000'
     'Size': '9'
     'Moons': 'A,B,C'
     'Gravity': '0.4'
     'Elements Found': 'H, HE, C'
     'Orbiting Time': '15'
     'Day Time': '12'

   planet
     'Name': 'Pluto'
     'Distance from the Earth': '100000'
     'Size': '9'
     'Moons': 'A,B,C'
     'Gravity': '0.4'
     'Elements Found': 'H, HE, C'
     'Orbiting Time': '15'
     'Day Time': '12'

This variation loads the data into a dictionary containing two lists, one for stars & one for planets. Each of those lists contains a dictionary for each body found in that category. We can use the json module to print the data nicely.

import xml.etree.ElementTree as ET
import json

root = ET.fromstring(data)

bodies = {}
for kind in root:
    bodies[kind.tag] = bodylist = []
    for child in kind:
        bodylist.append({item.attrib['name']: item.text for item in child})

print(json.dumps(bodies, indent=4))

output

 {
    "stars": [
        {
            "Name": "Sun",
            "Distance from the Earth": "100000",
            "Size": "9",
            "Moons": "A,B,C",
            "Gravity": "0.4",
            "Elements Found": "H, HE",
            "Orbiting Time": "15",
            "Day Time": "12"
        }
    ],
    "planets": [
        {
            "Name": "Mercury",
            "Distance from the Earth": "100000",
            "Size": "9",
            "Moons": "A,B,C",
            "Gravity": "0.4",
            "Elements Found": "H, HE, C",
            "Orbiting Time": "15",
            "Day Time": "12"
        },
        {
            "Name": "Venus",
            "Distance from the Earth": "100000",
            "Size": "9",
            "Moons": "A,B,C",
            "Gravity": "0.4",
            "Elements Found": "H, HE, C",
            "Orbiting Time": "15",
            "Day Time": "12"
        },
        {
            "Name": "Earth",
            "Distance from the Earth": "0",
            "Size": "9",
            "Moons": "A,B,C",
            "Gravity": "0.4",
            "Elements Found": "H, HE, C",
            "Orbiting Time": "15",
            "Day Time": "12"
        },
        {
            "Name": "Mars",
            "Distance from the Earth": "100000",
            "Size": "9",
            "Moons": "A,B,C",
            "Gravity": "0.4",
            "Elements Found": "H, HE, C",
            "Orbiting Time": "15",
            "Day Time": "12"
        },
        {
            "Name": "Jupiter",
            "Distance from the Earth": "100000",
            "Size": "9",
            "Moons": "A,B,C",
            "Gravity": "0.4",
            "Elements Found": "H, HE, C",
            "Orbiting Time": "15",
            "Day Time": "12"
        },
        {
            "Name": "Saturn",
            "Distance from the Earth": "100000",
            "Size": "9",
            "Moons": "A,B,C",
            "Gravity": "0.4",
            "Elements Found": "H, HE, C",
            "Orbiting Time": "15",
            "Day Time": "12"
        },
        {
            "Name": "Uranus",
            "Distance from the Earth": "100000",
            "Size": "9",
            "Moons": "A,B,C",
            "Gravity": "0.4",
            "Elements Found": "H, HE, C",
            "Orbiting Time": "15",
            "Day Time": "12"
        },
        {
            "Name": "Neptune",
            "Distance from the Earth": "100000",
            "Size": "9",
            "Moons": "A,B,C",
            "Gravity": "0.4",
            "Elements Found": "H, HE, C",
            "Orbiting Time": "15",
            "Day Time": "12"
        },
        {
            "Name": "Pluto",
            "Distance from the Earth": "100000",
            "Size": "9",
            "Moons": "A,B,C",
            "Gravity": "0.4",
            "Elements Found": "H, HE, C",
            "Orbiting Time": "15",
            "Day Time": "12"
        }
    ]
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.