ElementTree Returns Element Instead of ElementTree

ElToro1966 picture ElToro1966 · Nov 27, 2015 · Viewed 7.9k times · Source

I am trying to build an ElementTree from a string. When I do the following (as set out in Python ElementTree: Parsing a string and getting ElementTree instance), I get an Element instead of an ElementTree:

companyTree = ElementTree.ElementTree(ElementTree.fromstring('<companies></companies>'))

If I do

print(companyTree.getroot())

I get

AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getroot'

In other words, companyTree is an Element instead of an ElementTree. According to the accepted answer in 1, I should be getting an ElementTree. Has the API changed? How do I get an ElementTree from a string now? Thanks.

Note that there is more on this problem in Python ElementTree: ElementTree vs root Element

Answer

killthrush picture killthrush · Jun 11, 2017

This one bit me too. I had some old code kicking around that used parse(). I refactored to use fromstring(), causing the same error. Based on your references, I can summarize what's going on here; I believe this will be beneficial for people getting this specific error. The other articles deal directly with the API itself so I wouldn't consider them duplicates.

So, first to address this point. You are correct that the stated issue is related, however I don't think the accepted answer is making the claim that fromstring() is supposed to return an ElementTree. Rather, the author of this answer is saying in the context of the problem the string is equivalent to a complete XML document rather than a fragment, so it's appropriate to convert it to an ElementTree:

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.

And in his code sample, he does just that:

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

This approach is confirmed by the second reference you posted, which links an old article by the library's author, in which he states (and I paraphrase) that this is not a design quirk, it's a feature. The expectation is that constructs like parse() are designed to work with complete documents and fromstring() is designed to work with fragments and documents. It's just in this latter case that we the programmer must resolve the ambiguity and inform the library that we expect the string to be a complete document.

So, as far as my use case goes, I had a complete document in my XML string and wanted the ElementTree features, so I wrapped my fromstring() call in an ElementTree as in the example above.