Get Xpath dynamically using ElementTree getpath()

elementtree, lxml, python, xpath

Solution

Rather than trying to construct a full path from the root, you can evaluate XPath expression on with the entry as the base node:

tree = etree.parse(xmlFileUrl)
nsmap = {'def':'http://www.w3.org/2005/Atom'}
entries_expr = etree.XPath('//def:entry', namespaces=nsmap)
category_expr = etree.XPath('category')
for entry in entries_expr(tree):
    category = category_expr(entry)

If performance is not critical, you can simplify the code by using the `.xpath()` method on elements rather than pre-compiled expressions:

tree = etree.parse(xmlFileUrl)
nsmap = {'def':'http://www.w3.org/2005/Atom'}
for entry in tree.xpath('//def:entry', namespaces=nsmap):
    category = entry.xpath('category')

Problem

I need to write a dynamic function that finds elements on a subtree of an ATOM xml by building dynamically the XPath to the element. To do so, I've written something like this: ``` tree = etree.parse(xmlFileUrl) e = etree.XPathEvaluator(tree, namespaces={'def':'http://www.w3.org/2005/Atom'}) entries = e('//def:entry') for entry in entries: mypath = tree.getpath(entry) + "/category" category = e(mypath) ``` The code above fails to find "category" because getpath() returns an XPath without namespaces, whereas the XPathEvaluator e() requires namespaces. Although I know I can use the path and provide a namespace in the call to XPathEvaluator, I would like to know if it's possible to make getpath() return a "fully qualified" path, using all the namespaces, as this is convenient in certain cases. (This is a spin-off question of my earlier question: Python XpathEvaluator without namespace)

Original source