Using an xpath query with Python etree to find a value of a node with the same parent path as another node

Recently I needed to search through an xml document using Python for a specific key / value pair and get the text value of a sibling node. For the most part this xml structure was going to be the same every time, but the text value of one of the nodes would change. We’re already using the etree library, here’s how I did it…

Here’s the sample xml structure:

<parameters>
    <parameter>
        <name>abc</name>
        <value>111</value>
    </parameter>
    <parameter>
        <name>efg</name>
        <value>222</value>
    </parameter>
    <parameter>
        <name>hij</name>
        <value>333</value>
    </parameter>
</parameters>

Not an optimal structure but it’s what I’ve got to work with.

Now, let’s say we need to pull out the value node of the parameter with the name “efg”. We will need to search the document for the parent node and pull out the text in the value child node.

Here’s the code …

#!/usr/bin/env python
try:
    import xml.etree.cElementTree as ET
except (AttributeError, ImportError):
    import xml.etree.ElementTree as ET

the_xml = """<parameters>
    <parameter>
        <name>abc</name>
        <value>111</value>
    </parameter>
    <parameter>
        <name>efg</name>
        <value>222</value>
    </parameter>
    <parameter>
        <name>hij</name>
        <value>333</value>
    </parameter>
</parameters>"""

def get_param_value_by_name(xml, name):
    """finds the value of a parameter with a variable name"""

    root = ET.fromstring(xml)
    path = "./parameter/[name='" + name + "']"
    node = root.findall(path)
    if node:
        #print ET.tostring(node[0])
        return_val = node[0].findtext("./value", "")
        #print return_val
    else:
        return_val = None
    del(root)

    return return_val

v = get_param_value_by_name(the_xml, "efg")
print v

A couple things to note…

The try, except block at the top attempts to load the “c” version of etree if it is available on the platform which the script is going to run. This is a good practice no matter what you use etree for, if the c version is available the interpreter will use that and it’s much faster. Otherwise the pure python version of etree will be used.

Next, inside of the function an xpath query string is constructed and searched for using findall. If there is a node tagged “name” with value equal to the name parameter, that node is retrieved. In this example we are only looking for the first instance in the list of nodes returned, you can modify that if it suites your purposes.

findtext is used to get the value of the node tagged “value” and return those results. If either the original search node is not found or there is no value node found, None is returned.

Advertisements
Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: