Question

I am using sikuli (a Jython language although it's mostly python) to transverse a xml tree looking for a specific element.

if i write the code like this:

xmldoc = ('/ProgramData/XXXXX/XXXXX/XXXX/file.xml')
tree = ET.parse(xmldoc)
root = tree.getroot()
transverse(root)

def transverse(Root):
    for x in Root:
        if(x.tag=='ecuID'):
            if (x.get('id')=='16'):
                print x.get('corner')
        else:
            transverse(x)

The console prints (5,105) (this is the value of x.get('corner'))

if the code is like this

xmldoc = ('/ProgramData/XXXXX/XXXXX/XXXX/file.xml')
tree = ET.parse(xmldoc)
root = tree.getroot()
print transverse(root)

def transverse(Root):
    for x in Root:
        if(x.tag=='ecuID'):
            if (x.get('id')=='16'):
                return x.get('corner')
        else:
           return transverse(x)

the log prints out None. I feel that it should behave the same either way and i actually need it to work the second way.

i think the code is returning the first time it gets to the else statement instead of waiting for a result to be filtered back to the top if you understand what i mean by that.

Any help as to why these to code segments behave differently would be greatly apriciated

Was it helpful?

Solution

If for all x in Root, x.tag == 'ecuID' is True but x.get('id') == '16' is not True, then the loop never reaches a return statement, and None is returned instead.

This also happens when Root is an empty sequence, like for any leaf element in your node tree.

If any <ecuID id="16"> node is encountered where there is no node attribute, then None is returned as well, as x.get('corner') would return the default instead.

Instead of recursing, why not use a stack approach?

def traverse(node):
    stack = [node]
    while stack:
        next = stack.pop()
        for node in next:
            if node.tag == 'ecuID' and node.get('id') == '16':
                return node.get('corner')
            stack.append(node)

This'll traverse the tree as well, visiting all nodes until your node is found or None is returned when there is no matching node.

Best of all would just to be the getiterator() method:

def traverse(root):
    for node in root.getiterator('ecuID'):
        if node.get('id') == '16':
            return node.get('corner')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top