3

I'm trying to locate an element that has certain text value in one of its child. For example,

<peers>
    <peer>
        <offset>1</offset>
        <tag>TRUE</tag>
    </peer>
    <peer>
        <offset>2</offset>
        <tag>FALSE</tag>
    </peer>
</peers>

from this XML document I would like to directly locate tag in a peer element whose offset value is 1.

So for that purpose I have a XPath expression as follows:

./peers/peer[offset='1']/tag

however using such expression in ElementTree's Element.find() method fails and gives None rather than the "tag" element of my interest:

from xml.etree.ElementTree import fromstring

doc = fromstring("<peers><peer><offset>1</offset><tag>TRUE</tag></peer><peer><offset>2</offset><tag>FALSE</tag></peer></peers>")

tag = doc.find("./peers/peer[offset='1']/tag")

print tag


=> None

I'm being inclined to believe it's either my above XPath expression is wrong, or due to ElementTree's supporting only a subset of XPath according to its documentation. Looking for help. Thank you.

1
  • Your XPath expression is totally fine, it's ElementTree's implementation that is horribly incapable. Commented Mar 2, 2014 at 23:56

1 Answer 1

5

Using lxml.etree directly (the same should apply to ElementTree), you can achieve the result like this:

doc = lxml.etree.fromstring(...)
tag_elements = doc.xpath("/peers/peer/offset[text()='1']/../tag")

tag_elements will be the list of <tag> elements belonging to <peer> elements containing an <offset> element containing 1.

Given input (I've added a <peer> clause to emphasize tag_elements being a list):

<peers>
    <peer>
        <offset>1</offset>
        <tag>TRUE</tag>
    </peer>
    <peer>
        <offset>1</offset>
        <tag>OTHER</tag>
    </peer>
    <peer>
        <offset>2</offset>
        <tag>FALSE</tag>
    </peer>
</peers>

tag_elements will contain two elements:

for tag in tag_elements:
    print tag.text
-> TRUE
-> OTHER

UPDATE:

doc.xpath("/peers/peer[offset=1]/tag") also works fine.

But doc.xpath("./peers/peer[offset=1]/tag") does not.

Sign up to request clarification or add additional context in comments.

2 Comments

Just trying your suggestion in ElementTree raises SyntaxError: cannot use absolute path on element I see many people referring to lxml when asked about the use of XPath in ElementTree. Should I really use lxml instead?
personally, I gave up on ElementTree... and I get by just fine with lxml.etree.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.