简体   繁体   中英

Python - Using attributes to parse XML tree

There are a lot of examples on how to parse XML using tags in the tree, but what if (as in the example below) many of the tags have the same name?

<SoccerFeed timestamp="20161221T144346+0000">
  <SoccerDocument Type="SQUADS Latest">
    <Team country="USA">
      <Founded>1998</Founded>
      <Name>Chicago Fire</Name>
      <Player uID="p113757">
        <Name>Patrick McLain</Name>
        <Position>Goalkeeper</Position>
        <Stat Type="first_name">Patrick</Stat>
        <Stat Type="last_name">McLain</Stat>
        <Stat Type="birth_date">1988-08-22</Stat>
        <Stat Type="birth_place">Eau Claire</Stat>
        <Stat Type="first_nationality">USA</Stat>
        <Stat Type="weight">94</Stat>
        <Stat Type="height">191</Stat>
        <Stat Type="jersey_num">23</Stat>
        <Stat Type="real_position">Goalkeeper</Stat>
        <Stat Type="real_position_side">Unknown</Stat>
        <Stat Type="join_date">2016-01-18</Stat>
        <Stat Type="country">USA</Stat>
      </Player>
    </Team>
  </SoccerDocument>
</SoccerFeed>

If I wanted to parse only elements with a 'Stat' tag and a 'first_name' attribute, how would I do that?

You can use BeautifulSoup within XML parser, like this example:

from bs4 import BeautifulSoup as bs

data = '''<SoccerFeed timestamp="20161221T144346+0000">
  <SoccerDocument Type="SQUADS Latest">
    <Team country="USA">
      <Founded>1998</Founded>
      <Name>Chicago Fire</Name>
      <Player uID="p113757">
        <Name>Patrick McLain</Name>
        <Position>Goalkeeper</Position>
        <Stat Type="first_name">Patrick</Stat>
        <Stat Type="last_name">McLain</Stat>
        <Stat Type="birth_date">1988-08-22</Stat>
        <Stat Type="birth_place">Eau Claire</Stat>
        <Stat Type="first_nationality">USA</Stat>
        <Stat Type="weight">94</Stat>
        <Stat Type="height">191</Stat>
        <Stat Type="jersey_num">23</Stat>
        <Stat Type="real_position">Goalkeeper</Stat>
        <Stat Type="real_position_side">Unknown</Stat>
        <Stat Type="join_date">2016-01-18</Stat>
        <Stat Type="country">USA</Stat>
      </Player>
    </Team>
  </SoccerDocument>
</SoccerFeed>'''

sub = bs(data, 'xml')
# Find all the 'Stat' tags
stat_tags = sub.findAll('Stat')
for k in stat_tags:
    # Extract the text between 'Stat' tags
    print(k.text)

Output:

Patrick
McLain
1988-08-22
Eau Claire
USA
94
191
23
Goalkeeper
Unknown
2016-01-18
USA

Using R and the xml2 library:

library("xml2")
myxml<-read_xml('<SoccerFeed timestamp="20161221T144346+0000">
<SoccerDocument Type="SQUADS Latest">
<Team country="USA">
<Founded>1998</Founded>
<Name>Chicago Fire</Name>
<Player uID="p113757">
<Name>Patrick McLain</Name>
<Position>Goalkeeper</Position>
<Stat Type="first_name">Patrick</Stat>
<Stat Type="last_name">McLain</Stat>
<Stat Type="birth_date">1988-08-22</Stat>
<Stat Type="birth_place">Eau Claire</Stat>
<Stat Type="first_nationality">USA</Stat>
<Stat Type="weight">94</Stat>
<Stat Type="height">191</Stat>
<Stat Type="jersey_num">23</Stat>
<Stat Type="real_position">Goalkeeper</Stat>
<Stat Type="real_position_side">Unknown</Stat>
<Stat Type="join_date">2016-01-18</Stat>
<Stat Type="country">USA</Stat>
</Player>
</Team>
</SoccerDocument>
</SoccerFeed>')

#get all of the Stat nodes
statnodes<-xml_nodes(myxml, "Stat")
#filter for first_name node
firstname<- statnodes[xml_attr(statnodes, "Type" )== "first_name"]
#get text value
xml_text(firstname)

With ElementTree:

for firstnames in root.findall('Team/Player/Stat[@type="first_name"]')
    print(firstnames.attrib)

Complete XPath-Syntax: https://docs.python.org/3.6/library/xml.etree.elementtree.html#supported-xpath-syntax

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM