22

I have a string containing XML data that is returned from an http request.

I am using ElementTree to parse the data, and I want to then search recursively for an element.

According to this question, I can only search recursively with result.findall() if result is of type ElementTree rather than type Element.

Now xml.etree.ElementTree.fromstring() , used to parse the string, returns an Element object, while xml.etree.ElementTree.parse(), used to parse a file, returns an ElementTree object.

My question is then: How can I parse the string and get an ElementTree instance? (without any madness like writing to a temporary file)

Community
  • 1
  • 1
YXD
  • 31,741
  • 15
  • 75
  • 115

2 Answers2

32

When you use ElementTree.fromstring() what you're getting back is basically the root of the tree, so if you create a new tree like this ElementTree.ElementTree(root) you'll get you're looking for.

So, to make it clearer:

from xml.etree import ElementTree
tree = ElementTree.ElementTree(ElementTree.fromstring(<your_xml_string>))

or:

from xml.etree.ElementTree import fromstring, ElementTree
tree = ElementTree(fromstring(<your_xml_string>))
jcollado
  • 39,419
  • 8
  • 102
  • 133
  • I just want to add - for those using lxml - that in lxml (where an element always belongs to a document/tree, even if implicit), you can use the getrootttree() method. – Steven Dec 21 '11 at 11:12
  • 1
    Thanks! Really annoying API design in etree, to have different types of output just depending on the input source. Really confusing :( – Samuel Lampa Mar 22 '13 at 13:43
  • 1
    This really isn't very clear in the documentation. "fromstring() parses XML from a string directly into an Element, which is the root element of the parsed tree. Other parsing functions may create an ElementTree." – Snorfalorpagus Nov 20 '13 at 14:32
8

Turn your string into a file-like object and use ElementTree.parse:

from xml.etree import ElementTree
from cStringIO import StringIO

tree = ElementTree.parse(StringIO(string))
ekhumoro
  • 115,249
  • 20
  • 229
  • 336