Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ElementTree Returns Element Instead of ElementTree

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

like image 468
ElToro1966 Avatar asked Nov 27 '15 17:11

ElToro1966


People also ask

What is xml etree ElementTree?

The xml. etree. ElementTree module implements a simple and efficient API for parsing and creating XML data. Changed in version 3.3: This module will use a fast implementation whenever available.

What does Etree parse do?

Parsing from strings and files. lxml. etree supports parsing XML in a number of ways and from all important sources, namely strings, files, URLs (http/ftp) and file-like objects. The main parse functions are fromstring() and parse(), both called with the source as first argument.


1 Answers

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.

like image 186
killthrush Avatar answered Oct 13 '22 00:10

killthrush