代码之家  ›  专栏  ›  技术社区  ›  Schütze

在Python 3中循环分析XML数据以创建多个对象

  •  0
  • Schütze  · 技术社区  · 6 年前

    我有以下XML结构:

    <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>
    

    我想把它们读入Python 3中创建的对象中。

    我有以下循环:

    # 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)
    

    但正如您所看到的,我不想自己硬编码行星,而是希望以一种好的方式从XML文件中获取数据。所以我不应该说“水星”,它应该穿过树,把每个天体的值转换成变量,然后创造出物体。

    我无法完成的是XML读取部分。不管我尝试了什么,我都无法循环遍历级别来将值读入变量。我已经试过美化组,lxml,ET,但是没有运气。

    一些试验:

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

    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)
    

    每个结果都有错误。应该有一种直截了当的方法。

    有什么建议吗?

    编辑: 因此,有了以下几点,我可以联系到这两个孩子,但不能再联系了:

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

    输出:

    stars {}
    planets {}
    

    如何在其中循环并检索值?

    3 回复  |  直到 6 年前
        1
  •  2
  •   Никита Мартынов    6 年前

    首先,您可以找到行星和恒星元素,将它们添加到列表中并从中选择第一个值。

    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")
    
        2
  •  2
  •   Jonathan R    6 年前

    使用etree的代码可以工作。您缺少一行只返回 item 具有 name 设置为某个值。

    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, ...)
    

    从这里你应该可以自己解决剩下的问题。希望有帮助。

        3
  •  0
  •   PM 2Ring    6 年前

    这里有一个在数据结构上迭代的简单方法。为了保持代码的自包含性,我直接从字符串读取XML,而不是从文件读取。

    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()
    

    输出

    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'
    

    这种变化将数据加载到包含两个列表的字典中,一个用于恒星,一个用于行星。这些列表中的每一个都包含该类别中找到的每个正文的词典。我们可以使用 json 模块可以很好地打印数据。

    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))
    

    输出

     {
        "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"
            }
        ]
    }