3

About as simple as it should get:

<state name = "foo1>
    <foobar item1="something1" item2="somethingelse1" item3="usefulitem1"/>
    <foobar item1="something2" item2="somethingelse2" item3="usefulitem2"/>
<state name = "foo2">
...
root = lxml.etree.parse(fileName)
path = "./*[contains(text(),'useful')]"
someElement = root.xpath(path)

I'm trying to make a list of all the foobar's that have some item with the text 'useful' somewhere in it. I keep getting the error TypeError: 'lxml.etree._ElementTree' object is not iterable

Veggicide
  • 31
  • 3

1 Answers1

2

I actually thought you would be able to XPath from a tree object. Huh. But you definitely can't iterate over it. To do that you need to get the root (element).

From the docs:

getroot(self)
Gets the root element for this tree.

So your code would look something like this instead.

<state name = "foo1>
    <foobar item1="something1" item2="somethingelse1" item3="usefulitem1"/>
    <foobar item1="something2" item2="somethingelse2" item3="usefulitem2"/>
<state name = "foo2">
...
tree = lxml.etree.parse(fileName)
root = tree.getroot()
path = "./*[contains(text(),'useful')]"
someElement = root.xpath(path)

The tricky thing is that when you use .fromstring instead of a file then you automatically have the root element, rather than an ElementTree.

grofte
  • 1,839
  • 1
  • 16
  • 15
  • But I agree that your xml file looks weird. I would have expected something more like in this question: https://stackoverflow.com/questions/4531995/getting-attribute-using-xpath?rq=1 – grofte Mar 31 '21 at 11:03
  • 1
    `tree.getroot()` is not needed. The `xpath()` method is available on both `Element` and `ElementTree` objects. – mzjn Mar 31 '21 at 16:29