How to get the child of child using Python's ElementTree
Asked Answered
C

1

9

I'm building a Python file that communicates with a PLC. When compiling, the PLC creates a XML file that delivers important information about the program. The XML looks more less like this:

<visu>
    <time>12:34</time>
    <name>my_visu</name>
    <language>english</language>
    <vars>
        <var name="input1">2</var>
        <var name="input2">45.6</var>
        <var name="input3">"hello"</var>
    </vars>
</visu>

The important part is found under child "vars". Using Python I want to make a file that when sending argument "input2" it will print "45.6".

So far I can read all children of "visu", but don't know how to actually tell Python to search among "the child of child". Here's is what I got so far:

tree = ET.parse("file.xml")
root = tree.getroot()
for child in root:
    if child.tag == "vars":
        .......
        if ( "childchild".attrib.get("name") == "input2" ):
            print "childchild".text

Any ideas how I can complete the script? (or maybe a more efficient way of programming it?)

Chiasmus answered 1/3, 2015 at 1:23 Comment(0)
P
10

You'd be better of using an XPath search here:

name = 'input2'
value = root.find('.//vars/var[@name="{}"]'.format(name)).text

This searches for a <var> tag directly below a <vars> tag, whose attribute name is equal to the value given by the Python name variable, then retrieves the text value of that tag.

Demo:

>>> from xml.etree import ElementTree as ET
>>> sample = '''\
... <visu>
...     <time>12:34</time>
...     <name>my_visu</name>
...     <language>english</language>
...     <vars>
...         <var name="input1">2</var>
...         <var name="input2">45.6</var>
...         <var name="input3">"hello"</var>
...     </vars>
... </visu>
... '''
>>> root = ET.fromstring(sample)
>>> name = 'input2'
>>> root.find('.//vars/var[@name="{}"]'.format(name)).text
'45.6'

You can do this the hard way and manually loop over all the elements; each element can be looped over directly:

name = 'input2'
for elem in root:
    if elem.tag == 'vars':
        for var in elem:
           if var.attrib.get('name') == name:
               print var.text

but using element.find() or element.find_all() is probably going to be easier and more concise.

Propagation answered 1/3, 2015 at 1:26 Comment(1)
Thanks for answering, I´ll implement the solution with find().Puffball

© 2022 - 2024 — McMap. All rights reserved.