1

I am trying to write a Python script that prints the value of a particular tag in an XML output. Here, the tag value I need to print is the value of in each and every occurrences in the XML output. I tried as below, but it shows an attribute error. What could be wrong here? Which is the correct way of getting and print values of certain more tags which I am interested to see? Any help please? Thanks.

import xml.etree.ElementTree as ET

mystring="""<?xml version="1.0" encoding="UTF-8"?>
<main>
    <student>
        <male>
            <result>pass</result>
            <name>Paul</name>
            <address>boston</address>
            <localreference>
                <name>Charlie</name>
            </localreference>
        </male>
        <female>
            <result>pass</result>
            <name>Rose</name>
            <address>newyork</address>
            <localreference>
                <name>Charlie</name>
            </localreference>
        </female>
    </student>
    <student>
        <male>
            <result>fail</result>
            <name>Philippe</name>
            <address>boston</address>
            <localreference>
                <name>White</name>
            </localreference>
        </male>
    </student>
</main>"""

main = ET.fromstring(mystring)
for student in main:
  if (student.tag == "student"):
      print student.find("male/result").text
      print student.find("female/result").text

Error>

# python new5.py
pass
pass
fail
Traceback (most recent call last):
  File "new5.py", line 39, in <module>
    print student.find("female/result").text
AttributeError: 'NoneType' object has no attribute 'text'

2 Answers 2

0

ElementTree supports a subset of XPath, and that may be easier for your example:

root = ET.fromstring(mystring)
for gender in ('male', 'female'):
    print gender
    for student in root.findall('./student/%s' % gender): 
        print '\t{:20}: {}'.format(student.find('name').text, student.find('result').text)

Prints:

male
    Paul                : pass
    Philippe            : fail
female
    Rose                : pass

(btw: avoid using main as a variable name since you clobber the name of the main module)


If you want the results in document order rather than grouped by gender, you might do something like:

for students in root.findall('./student'):
    for gender in students:
        print ' '.join([gender.tag] + map(lambda a: gender.find(a).text, ('name', 'address', 'result', 'localreference/name')))

Prints

male Paul boston pass Charlie
female Rose newyork pass Charlie
male Philippe boston fail White
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks Dawg. However i get this error. # python new5.py male Traceback (most recent call last): File "new5.py", line 40, in <module> print '\t{:20}: {}'.format(student.find('name').text, student.find('result').text) ValueError: zero length field name in format
What version os Python? You probably have Python 2.6. Use '\t{0:20}: {1}' for the format string.
Awesome, that worked. I am using 2.6.6 . Sorry to ask, I am a beginner here, would you mind explaining the last print statement? print '\t{:20}: {}'.format(student.find('name').text, student.find('result').text) Thanks Dawg..
It is the Python format mini language
0

Your code for printing a tag value is correct, but you are asking for a section of your xml that does not exist. There is no female section in the second student section. This is why student.find("female/result") is returning None on the second student, and you cannot call .text on a None object.

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.