pythonxmlpython-2.7parsing

Parse a xml file with multiple root element in python


i have a xml file, and i need to fetch some of the tags from it for some use, which have data like:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank>1</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank>4</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank>68</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>
<?xml version="1.0"?>
<data>
    <country name="Liechtenstein1">
        <rank>1</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria1" direction="E"/>
        <neighbor name="Switzerland1" direction="W"/>
    </country>
    <country name="Singapore">
        <rank>4</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia1" direction="N"/>
    </country>
    <country name="Panama">
        <rank>68</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

i need to parse this, so i used:

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

this code giving error at line 2: xml.etree.ElementTree.ParseError: junk after document element:

i think this is because multiple xml tags, do you have any idea, how should i parse this?


Solution

  • This code fills in details for one approach, if you want them.

    The code watches for 'accumulated_xml until it encounters the beginning of another xml document or the end of the file. When it has a complete xml document it calls display to exercise the lxml library to parse the document and report some of the contents.

    >>> from lxml import etree
    >>> def display(alist):
    ...     tree = etree.fromstring(''.join(alist))
    ...     for country in tree.xpath('.//country'):
    ...         print(country.attrib['name'], country.find('rank').text, country.find('year').text)
    ...         print([neighbour.attrib['name'] for neighbour in country.xpath('neighbor')])
    ... 
    >>> accumulated_xml = []
    >>> with open('temp.xml') as temp:
    ...     while True:
    ...         line = temp.readline()
    ...         if line:
    ...             if line.startswith('<?xml'):
    ...                 if accumulated_xml:
    ...                     display (accumulated_xml)
    ...                     accumulated_xml = []
    ...             else:
    ...                 accumulated_xml.append(line.strip())
    ...         else:
    ...             display (accumulated_xml)
    ...             break
    ... 
    Liechtenstein 1 2008
    ['Austria', 'Switzerland']
    Singapore 4 2011
    ['Malaysia']
    Panama 68 2011
    ['Costa Rica', 'Colombia']
    Liechtenstein1 1 2008
    ['Austria1', 'Switzerland1']
    Singapore 4 2011
    ['Malaysia1']
    Panama 68 2011
    ['Costa Rica', 'Colombia']