xml – How to use XPath in Python?

xml – How to use XPath in Python?

libxml2 has a number of advantages:

  1. Compliance to the spec
  2. Active development and a community participation
  3. Speed. This is really a python wrapper around a C implementation.
  4. Ubiquity. The libxml2 library is pervasive and thus well tested.

Downsides include:

  1. Compliance to the spec. Its strict. Things like default namespace handling are easier in other libraries.
  2. Use of native code. This can be a pain depending on your how your application is distributed / deployed. RPMs are available that ease some of this pain.
  3. Manual resource handling. Note in the sample below the calls to freeDoc() and xpathFreeContext(). This is not very Pythonic.

If you are doing simple path selection, stick with ElementTree ( which is included in Python 2.5 ). If you need full spec compliance or raw speed and can cope with the distribution of native code, go with libxml2.

Sample of libxml2 XPath Use


import libxml2

doc = libxml2.parseFile(tst.xml)
ctxt = doc.xpathNewContext()
res = ctxt.xpathEval(//*)
if len(res) != 2:
    print xpath query: wrong node set size
    sys.exit(1)
if res[0].name != doc or res[1].name != foo:
    print xpath query: wrong node set value
    sys.exit(1)
doc.freeDoc()
ctxt.xpathFreeContext()

Sample of ElementTree XPath Use


from elementtree.ElementTree import ElementTree
mydoc = ElementTree(file=tst.xml)
for e in mydoc.findall(/foo/bar):
    print e.get(title).text

The lxml package supports xpath. It seems to work pretty well, although Ive had some trouble with the self:: axis. Theres also Amara, but I havent used it personally.

xml – How to use XPath in Python?

Sounds like an lxml advertisement in here. 😉 ElementTree is included in the std library. Under 2.6 and below its xpath is pretty weak, but in 2.7+ much improved:

import xml.etree.ElementTree as ET
root = ET.parse(filename)
result = 

for elem in root.findall(.//child/grandchild):
    # How to make decisions based on attributes even in 2.6:
    if elem.attrib.get(name) == foo:
        result = elem.text
        break

Leave a Reply

Your email address will not be published.