6

I have the following xml file

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

I want to write python 3 code using ElementTree to get all country names. So the end result should be a dict or array of

['Liechtenstein','Singapore','Panama']

I am trying to do this using Xpath but getting nowhere. So my code is as follows

import xml.etree.ElementTree as ET
tree = ET.parse(xmlfile)
root = tree.getroot()

names = root.findall("./country/@name")

However the above does not work as I feel my xpath is wrong.

2 Answers 2

6

Use findall() to get all of the country tags and get the name attribute from the .attrib dictionary:

import xml.etree.ElementTree as ET

data = """your xml here"""

tree = ET.fromstring(data) 
print([el.attrib.get('name') for el in tree.findall('.//country')])

Prints ['Liechtenstein', 'Singapore', 'Panama'].

Note that you cannot get the attribute values using an xpath expression //country/@name since xml.etree.ElementTree provides only limited Xpath support.


FYI, lxml provides a more complete xpath support and therefore makes it easier to get the attribute values:

from lxml import etree as ET

data = """your xml here"""

tree = ET.fromstring(data)
print(tree.xpath('//country/@name'))

Prints ['Liechtenstein', 'Singapore', 'Panama'].

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

3 Comments

Thank you. Is it possible to all names into an array in a single line.
Figured it out. Thanks.
@VinayJoseph I've also added an lxml option - just in case you are okay with using third-party modules. And also added links to the documentation.
0

You could use

 import xml.etree.ElementTree as ET

 xml=ET.fromstring(contents)



xml.find('./element').attrib['key']

Chek the source here

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.