Home > Net >  Parsing an XML document using python. Cannot use any library that requires pip
Parsing an XML document using python. Cannot use any library that requires pip

Time:11-18

I'm parsing an XML document, and I need the book title & number value under Score and place them on a 2d list. My current code, can retrieve that data and place it on a list, but the problem is there's some sections in the XML file where the score is not present, and I need to be able to leave an indicator (ex. N/A) on the list to indicate that value is empty for that particular book title.

This is a sample, simplified version of the xml file. Please note, that this problem repeats throughout the much longer version of the xml file. So no code can use, 1 as an index to get past this problem.

<bookstore>
            <book>[A-23] Everyday Italian</book>
               <author>Giada De Laurentiis</author>
                   <year>2005</year>
                  <price>30.00</price>
               <field></field>
          <key id="6408">[A-23]Everyday Italian</key>
               <brief>Everyday Italian</brief>
                <success></success>
                        <province> id="256" key=".com.place.fieldtypes:float">
                    <name>Post</name>
                    <numbers>
                           <number></number>
                </numbers>
                 </province>
                        <province> id="490" key=".com.ave.fieldtypes:float">
                    <name>Score</name>
                    <numbers>
                           <number>4.0</number>
                </numbers>
                 </province>
                        <province> id="531" key=".com.spot.fieldtypes:float">
                    <name>Doc</name>
                    <numbers>
                           <number></number>
                </numbers>
                 </province>
   </bookstore>
<bookstore>
            <book>[A-42] Pottery</book>
               <author>Leo Di Plos</author>
                   <year>2012</year>
                  <price>25.00</price>
               <field></field>
          <key id="4502">[A-42] Pottery</key>
               <brief>Pottery</brief>
                <success></success>
                        <province> id="627" key=".com.tri.fieldtypes:float">
                    <name>Post</name>
                    <numbers>
                           <number></number>
                </numbers>
                 </province>
                        <province> id="124" key=".com.doct.fieldtypes:float">
                    <name>Doc</name>
                    <numbers>
                           <number></number>
                </numbers>
                 </province>
   </bookstore>
<bookstore>
            <book>[A-12] Skipping the Line</book>
               <author>Gloria Gasol</author>
                   <year>1999</year>
                  <price>22.00</price>
               <field></field>
          <key id="1468">[A-23]Skipping the Line</key>
               <brief>Skipping the Line</brief>
                <success></success>
                        <province> id="754" key=".com.cit.fieldtypes:float">
                    <name>Post</name>
                    <numbers>
                           <number></number>
                </numbers>
                 </province>
                        <province> id="211" key=".com.soct.fieldtypes:float">
                    <name>Score</name>
                    <numbers>
                           <number>12.0</number>
                </numbers>
                 </province>
                        <province> id="458" key=".com.lot.fieldtypes:float">
                    <name>Doc</name>
                    <numbers>
                           <number></number>
                </numbers>
                 </province>
   </bookstore>

This is my current code:

book = []
for book in root.iter('book'):
    item1 = book.text
    title.append(item1)

score = []
for province in root.iter('province'):
    for child in province:
        for grandchild in child:
            if re.match('^[ -]?\d*?\.\d $', grandchild.text) != None:
                item2 = float(grandchild.text)
                score.append(item2)

print(book, score)

The expected output is:

([A-23] Everyday Italian, 4.0), ([A-42] Pottery, N/A), ([A-12] Skipping the Line, 12.0)

But the actual output is:

([A-23] Everyday Italian, 4.0), ([A-42] Pottery, 12.0), ([A-12] Skipping the Line)

CodePudding user response:

python's strength is the speed in creating a solution, among others, using ready-made libraries. Why you don't use lib like xmltodict?

for single bookstore:

<bookstore>
    <book>[A-23] Everyday Italian</book>**

    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
    <field></field>
    <key id="6408">[A-23]Everyday Italian</key>
    <brief>Everyday Italian</brief>
    <success></success>
    <province> id="256" key=".com.place.fieldtypes:float">
        <name>Post</name>
        <numbers>
            <number></number>
        </numbers>
    </province>
    <province> id="490" key=".com.ave.fieldtypes:float">
                    **
        <name>Score</name>**
                    
        <numbers>
                           **
            <number>4.0</number>**
                
        </numbers>
    </province>
    <province> id="531" key=".com.spot.fieldtypes:float">
        <name>Doc</name>
        <numbers>
            <number></number>
        </numbers>
    </province>
</bookstore>

python code for read it:

import xmltodict

dict_data = xmltodict.parse(xml_data)
dict_data

title = dict_data["bookstore"]["book"]
score = dict_data["bookstore"]["province"][1]["numbers"]["number"]

Are You sure that your xml is correct? You should create something like list of bookstore objects e.g.:

<BookstoreList>
    <Bookstore>
        //data here
    </Bookstore>
    <Bookstore>
        //data here
    </Bookstore>
    // etc.
</BookstoreList>

CodePudding user response:

Here we go..

import xml.etree.ElementTree as ET

xml = '''<r>
    <bookstore>
        <book>[A-23] Everyday Italian</book>
        <author>Giada De Laurentiis</author>
        <year>2005</year>
        <price>30.00</price>
        <field></field>
        <key id="6408">[A-23]Everyday Italian</key>
        <brief>Everyday Italian</brief>
        <success></success>
        <province> id="256" key=".com.place.fieldtypes:float">
            <name>Post</name>
            <numbers>
                <number></number>
            </numbers>
        </province>
        <province> id="490" key=".com.ave.fieldtypes:float">
            <name>Score</name>
            <numbers>
                <number>4.0</number>
            </numbers>
        </province>
        <province> id="531" key=".com.spot.fieldtypes:float">
            <name>Doc</name>
            <numbers>
                <number></number>
            </numbers>
        </province>
    </bookstore>
    <bookstore>
        <book>[A-42] Pottery</book>
        <author>Leo Di Plos</author>
        <year>2012</year>
        <price>25.00</price>
        <field></field>
        <key id="4502">[A-42] Pottery</key>
        <brief>Pottery</brief>
        <success></success>
        <province> id="627" key=".com.tri.fieldtypes:float">
            <name>Post</name>
            <numbers>
                <number></number>
            </numbers>
        </province>
        <province> id="124" key=".com.doct.fieldtypes:float">
            <name>Doc</name>
            <numbers>
                <number></number>
            </numbers>
        </province>
    </bookstore>
    <bookstore>
        <book>[A-12] Skipping the Line</book>
        <author>Gloria Gasol</author>
        <year>1999</year>
        <price>22.00</price>
        <field></field>
        <key id="1468">[A-23]Skipping the Line</key>
        <brief>Skipping the Line</brief>
        <success></success>
        <province> id="754" key=".com.cit.fieldtypes:float">
            <name>Post</name>
            <numbers>
                <number></number>
            </numbers>
        </province>
        <province> id="211" key=".com.soct.fieldtypes:float">
            <name>Score</name>
            <numbers>
                <number>12.0</number>
            </numbers>
        </province>
        <province> id="458" key=".com.lot.fieldtypes:float">
            <name>Doc</name>
            <numbers>
                <number></number>
            </numbers>
        </province>
    </bookstore>
</r>
'''
root = ET.fromstring(xml)
data = []
for bs in root.findall('.//bookstore'):
    book = bs.find('book').text
    scores = [s.text for s in bs.findall('.//number') if s.text]
    score = 'N/A' if not scores else scores[0]
    data.append((book, score))
print(data)

output

[('[A-23] Everyday Italian', '4.0'), ('[A-42] Pottery', 'N/A'), ('[A-12] Skipping the Line', '12.0')]
  • Related