Navigating Nested XML Structures
The central workflow is convert, locate, then read: convert the XML string with fromstring, locate an element with find, and read either its text or one of its attributes.
Try it: XML Element Trees
How ET.fromstring() turns XML text into a tree of Elements (tag, attributes, .text), and how find(), findall() and iter() walk that tree along a path such as users/user.
How it works
- The parser reads start tags, text and end tags left to right, keeping a stack of open elements; each start tag becomes an Element that is a child of the element on top of the stack.
- Text before an element's first child becomes its .text (whitespace included); an end tag must match the open element or parsing stops with ParseError.
- findall(path) starts at the element it is called on (the root is not part of the path) and follows each path segment down one level of children.
- find(path) returns the first match or None; iter(tag) visits every element in document order, including the root.
- Reading .text, .tag or .get('attr') on each result gives the extracted values; reading an attribute from None raises AttributeError.
Default run (29 steps): ET.fromstring() receives 183 characters. The parser reads tags left to right and keeps a stack of open elements. … findall() returned a list of 2 elements; reading e.get('x') from each gives ['2', '7'].
Simplified: A small, hand-written XML parser for a subset: elements, attributes, text, self-closing tags, comments, CDATA, processing instructions and the five predefined entities plus numeric character references. DOCTYPE/DTDs and namespaces are not supported. Error messages follow Python's expat parser for these cases (column numbers can differ for non-ASCII documents). Paths support tags, *, ., //, [@attr], [@attr='v'], [tag] and [n].
Loading the simulation…
From Text to a Navigable Tree
An XML document held in a plain string is only a sequence of characters. Before your program can locate specific tags or extract values, it needs a structure that represents the XML nesting. ElementTree provides fromstring for this conversion. It reads the XML string and returns an Element object representing the root element, which becomes the entry point to the rest of the tree.
The central workflow is convert, locate, then read: convert the XML string with fromstring, locate an element with find, and read either its text or one of its attributes.
The Tree Created by fromstring
After conversion, the returned Element represents the XML root. Its tag identifies the root element, and the element provides access to the hierarchical structure formed by the nested XML elements. This is the important change in state: the data is no longer being treated as unstructured text; it is represented as an XML tree that program code can navigate.
Identifying the Root Element
An XML string has a root element named person and nested elements named name and phone. What does fromstring provide for the next navigation step?
- 1Convert
Pass the XML string to fromstring. The function parses the string and returns an Element object for the root element.
- 2Identify
The returned Element has the root tag person. This object is now the entry point to the complete XML tree.
- 3Navigate
Use the returned root Element when searching for nested tags with find.
fromstring changes the XML from plain text into a hierarchical Element structure that code can navigate.
Finding a Nested Element
Once you have the root Element, use find to locate an element by tag name. The method returns the first element with a matching tag name within the tree. The result is itself an Element object, so it can provide access to the selected element's text and attributes.
Think of find as producing a selected Element rather than producing the final value immediately. After locating a tag, you perform a second operation to extract what that element contains. For content between the opening and closing tags, use .text. For a value written as an attribute in the opening tag, use .get().
Reading Text and Attributes
Extracting Two Kinds of XML Data
Consider the XML string <book code="B7"><title>Learning XML</title></book>. After converting it into a tree, locate the title element and obtain the title text and the book code.
- 1Convert the string
Use fromstring to create the root Element for the book tree.
- 2Locate the title
Use find with the tag name title. The result is the Element containing the text Learning XML.
- 3Read element content
Use the selected title Element's .text property to obtain Learning XML.
- 4Read the attribute
Use the root book Element's .get() method with the attribute name code to obtain B7.
The title value comes from .text, while the book code comes from .get(). These are separate extraction operations because XML text and XML attributes are stored differently.
Text may include whitespace from the original XML formatting, including newlines and spaces. When the extracted value should not retain that surrounding whitespace, apply the .strip() method to the text value.
Missing Elements and Unclean Text
Common mistake Trying to navigate the original XML string as though it were already a tree.
What it looks likeSearching the plain string directly for an Element property.
Why it failsA plain string is only a sequence of characters. ElementTree navigation requires the structure returned by fromstring.
Do this insteadConvert the XML string first and use the returned root Element as the entry point.
Common mistake Using .text to retrieve an attribute.
What it looks likeTrying to obtain the value of code from an opening tag by reading the element's .text.
Why it failsText content and attributes are separate kinds of XML data.
Do this insteadUse .text for content between tags and .get() for a named attribute.
Common mistake Accessing .text or .get() without checking find's result.
What it looks likeCalling find for a tag that is not present and immediately accessing a property on the result.
Why it failsfind returns None when it cannot locate a matching tag. Accessing properties on that missing result can cause an error.
Do this insteadStore the result, check that it is a valid element, and only then access .text or .get().
Common mistake Assuming extracted text is free of formatting whitespace.
What it looks likeUsing text from an XML element formatted with newlines and spaces.
Why it failsWhitespace from the original XML can be included in the element's text.
Do this insteadUse .strip() when surrounding whitespace should be removed.
Treat the result of find as something that must be validated before use. A missing tag is a normal possibility in real XML documents, so check that the result is present before reading its text or attributes.
Apply the Extraction Pattern
For the XML string <person><name>Ada</name><phone> 555-0100 </phone></person>, describe the operations needed to convert the string into a tree, locate the phone element, and obtain clean phone text. Then explain how the process would differ if the phone value were stored as an attribute instead of between the tags.
Hints
- Begin with fromstring.
- Use find with the phone tag.
- Read the selected element with .text.
- Use .strip() if the surrounding spaces should be removed.
- Use .get() when the value is an attribute rather than element text.
- 1The dependable pattern is to convert, locate, and read. Convert the XML string into a tree with fromstring. Locate the first matching tag with find. Read content between tags with .text or retrieve an opening-tag attribute with .get(). Check the result of find before using it, and strip surrounding whitespace when necessary.
Key Takeaways
- fromstring converts XML text into a hierarchical tree and returns an Element representing the root.
- find locates the first element with a matching tag name and returns an Element or None.
- The .text property reads content between an element's opening and closing tags.
- The .get() method retrieves a named attribute value from an element.
- Check find results before accessing properties, and use .strip() when extracted text contains unwanted whitespace.