7

I have this XML file:

<domain type='kmc' id='007'>
  <name>virtual bug</name>
  <uuid>66523dfdf555dfd</uuid>
  <os>
    <type arch='xintel' machine='ubuntu'>hvm</type>
    <boot dev='hd'/>
    <boot dev='cdrom'/>
  </os>
  <memory unit='KiB'>524288</memory>
  <currentMemory unit='KiB'>270336</currentMemory>
  <vcpu placement='static'>10</vcpu>

Now, I want parse this and fetch its attribute value. For instance, I want to fetch the uuid field. So what should be the proper method to fetch it, in Python?

S.Ali
  • 632
  • 1
  • 5
  • 12
  • 6
    What have you tried? Googling "python xml" yields quite a few really useful results that should point you in the right direction. – Blender Sep 05 '12 at 21:34
  • there are a lot of examples but not pointing in the direction i want to go. I wnat to fetch attributes value. the examples i am seeing are to convert to xml file or to convert form an xml file – S.Ali Sep 05 '12 at 21:36

7 Answers7

28

Here's an lxml snippet that extracts an attribute as well as element text (your question was a little ambiguous about which one you needed, so I'm including both):

from lxml import etree
doc = etree.parse(filename)

memoryElem = doc.find('memory')
print memoryElem.text        # element text
print memoryElem.get('unit') # attribute

You asked (in a comment on Ali Afshar's answer) whether minidom (2.x, 3.x) is a good alternative. Here's the equivalent code using minidom; judge for yourself which is nicer:

import xml.dom.minidom as minidom
doc = minidom.parse(filename)

memoryElem = doc.getElementsByTagName('memory')[0]
print ''.join( [node.data for node in memoryElem.childNodes] )
print memoryElem.getAttribute('unit')

lxml seems like the winner to me.

Alan W. Smith
  • 23,261
  • 4
  • 66
  • 92
ron rothman
  • 16,048
  • 6
  • 38
  • 40
  • 2
    This method is also compatible with [`xml.etree.ElementTree`](https://docs.python.org/library/xml.etree.elementtree.html), which is included with Python 2 and 3. – Stevoisiak Jan 31 '18 at 16:14
  • The first try with lxml does not work for me ... when I want to acces .text it says that Nonetype object has no attribute 'text'. – yesIamFaded Apr 20 '21 at 08:09
13

XML

<data>
    <items>
        <item name="item1">item1</item>
        <item name="item2">item2</item>
        <item name="item3">item3</item>
        <item name="item4">item4</item>
    </items>
</data>

Python :

from xml.dom import minidom
xmldoc = minidom.parse('items.xml')
itemlist = xmldoc.getElementsByTagName('item') 
print "Len : ", len(itemlist)
print "Attribute Name : ", itemlist[0].attributes['name'].value
print "Text : ", itemlist[0].firstChild.nodeValue
for s in itemlist :
    print "Attribute Name : ", s.attributes['name'].value
    print "Text : ", s.firstChild.nodeValue
d.danailov
  • 9,278
  • 4
  • 49
  • 35
2

etree, with lxml probably:

root = etree.XML(MY_XML)
uuid = root.find('uuid')
print uuid.text
Ali Afshar
  • 39,783
  • 12
  • 90
  • 108
0

I would use lxml and parse it out using xpath //UUID

Mike Pennington
  • 40,496
  • 17
  • 132
  • 170
0

Other people can tell you how to do it with the Python standard library. I'd recommend my own mini-library that makes this a completely straight forward.

>>> obj = xml2obj.xml2obj("""<domain type='kmc' id='007'>
... <name>virtual bug</name>
... <uuid>66523dfdf555dfd</uuid>
... <os>
... <type arch='xintel' machine='ubuntu'>hvm</type>
... <boot dev='hd'/>
... <boot dev='cdrom'/>
... </os>
... <memory unit='KiB'>524288</memory>
... <currentMemory unit='KiB'>270336</currentMemory>
... <vcpu placement='static'>10</vcpu>
... </domain>""")
>>> obj.uuid
u'66523dfdf555dfd'

http://code.activestate.com/recipes/534109-xml-to-python-data-structure/

Wai Yip Tung
  • 17,176
  • 9
  • 41
  • 46
0

Above XML does not have closing tag, It will give

etree parse error: Premature end of data in tag

Correct XML is:

<domain type='kmc' id='007'>
  <name>virtual bug</name>
  <uuid>66523dfdf555dfd</uuid>
  <os>
    <type arch='xintel' machine='ubuntu'>hvm</type>
    <boot dev='hd'/>
    <boot dev='cdrom'/>
  </os>
  <memory unit='KiB'>524288</memory>
  <currentMemory unit='KiB'>270336</currentMemory>
  <vcpu placement='static'>10</vcpu>
</domain>
Stephen Rauch
  • 44,696
  • 30
  • 102
  • 125
0

You can try parsing it with using (recover=True). you can do something like this.

parser = etree.XMLParser(recover=True)
tree = etree.parse('your xml file', parser)

I used this recently and it worked for me, you can try and see but in case you need to do any more complecated xml data extractions, you can take a look at this code i wrote for some project handling complex xml data extractions.