Concepts / Parsing XML Files with ElementTree

Parsing XML Files with ElementTree

ET.fromstring() converts an XML string into a tree structure of Element objects, making the hierarchical data queryable.

  • Programming
Interactive lab

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

  1. 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.
  2. 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.
  3. 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.
  4. find(path) returns the first match or None; iter(tag) visits every element in document order, including the root.
  5. 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].

Educational simulation

Loading the simulation…

From Text to Structure

XML begins as text, but its opening and closing tags describe a hierarchy. ElementTree makes that hierarchy queryable in Python. The central operation is ET.fromstring(): it converts an XML string into a tree of Element objects. After conversion, you work with structured elements rather than treating the XML as one long string.

XML string<person>...</person>nameChuckpersonroot Elementphonetext contentemailhide=yesET.fromstring()childchildchild
How does one linear XML string become nested Element objects with parent-child relationships?

Conversion Step

What do you think happens?

What does ET.fromstring(data) return when data contains XML describing a person?

Reveal answer
Answer:

It returns an Element object representing the root element of the XML tree. In the described example, the root is the person element.

The conversion changes the way the data is represented: tree refers to a structured Element object rather than the original XML string. That object represents the entire hierarchy beneath the root.

Code walkthrough
data = '<person><name>Chuck</name><phone>...</phone><email hide="yes">...</email></person>'
tree = ET.fromstring(data)
  1. 1
    Before the conversion, data is an XML string.
  2. 2
    ET.fromstring(data) parses that XML string.
  3. 3
    After the conversion, tree is an Element object representing the person root and its child elements.
  • data holds the XML string.
  • ET.fromstring(data) parses the string into an Element tree.
  • tree represents the root person element and its hierarchy.

The root Element represents the outermost XML element. In the example described by the source, the root is person, and the tree contains three child elements: name, phone, and email. The resulting tree object does not behave like a printed copy of the original string. Instead, you interact with it through ElementTree operations such as find(), .text, and .get().

Finding Nested Elements

Once the XML has become a tree, find() searches that tree for the first element matching a given tag name. Calling tree.find('name') searches from the tree represented by tree and retrieves the name element. Calling tree.find('email') retrieves the email element described in the example.

personrootnameChucknamefind('name')phonetext contentemailhide=yeschildchildchildfirst matching tag
How does find() move through the tree to locate a specific nested element?
python
Key point

find() retrieves an element, not the element's text directly. After finding an element, use .text to read the content inside it or .get(attribute_name) to read one of its attributes.

Reading Element Data

email<emailhide="yes">...</email>.textelement content.get('hide')attribute valueread textread attribute
Where are an element's text value and attributes located, and how are they accessed?
python
Output (expected)
name_text is 'Chuck'; hide_value is 'yes'.

The .text property retrieves the text content inside an element. In the source example, tree.find('name').text returns Chuck. The .get(attribute_name) method retrieves the value of a named attribute. In that same example, tree.find('email').get('hide') returns yes.

python

Complete Extraction

Worked example

Parse and extract person data

Convert an XML string describing a person into an Element tree, then retrieve the name text and the email hide attribute.

  1. 1
    Create the XML string

    The XML string contains a person root with name, phone, and email child elements. The email element has a hide attribute.

  2. 2
    Parse the string

    Pass the XML string to ET.fromstring(). The returned Element represents the person root and its hierarchy.

  3. 3
    Find the name element

    Use tree.find('name') to retrieve the first element matching the name tag.

  4. 4
    Read the name text

    Use .text on the found name element. The source example gives Chuck.

  5. 5
    Find the email element

    Use tree.find('email') to retrieve the email element.

  6. 6
    Read the hide attribute

    Use .get('hide') on the email element. The source example gives yes.

Result

The XML string has become a structured tree, and the requested values are retrieved as the text Chuck and the attribute value yes.

Code walkthrough
data = '<person><name>Chuck</name><phone>...</phone><email hide="yes">...</email></person>'
tree = ET.fromstring(data)
name = tree.find('name').text
hidden = tree.find('email').get('hide')
  1. 1
    data contains the XML text.
  2. 2
    tree receives the Element object returned by ET.fromstring(data).
  3. 3
    tree.find('name') retrieves the name element, and .text retrieves Chuck.
  4. 4
    tree.find('email') retrieves the email element, and .get('hide') retrieves yes.
Output
name: Chuck
hidden: yes

Common Parsing Mistakes

  • Common mistake

    Treating the result of ET.fromstring() as if it were still a plain string.

    What it looks like

    After tree = ET.fromstring(data), continuing to handle tree as raw XML text.

    Why it fails

    The conversion produces an Element object representing the root and its hierarchy.

    Do this instead

    Use tree methods and element access such as find(), .text, and .get().

  • Common mistake

    Expecting find() to return the text value directly.

    What it looks like

    Using tree.find('name') as though it directly returned Chuck.

    Why it fails

    find() returns the matching element.

    Do this instead

    Use tree.find('name').text to retrieve the element's text content.

  • Common mistake

    Using .text to retrieve an attribute.

    What it looks like

    Using tree.find('email').text when the needed value is hide="yes".

    Why it fails

    The text property reads content inside the element, while attributes are retrieved with .get(attribute_name).

    Do this instead

    Use tree.find('email').get('hide') for the hide attribute.

  • Common mistake

    Assuming whitespace is automatically removed.

    What it looks like

    Reading text that contains formatting spaces or line breaks.

    Why it fails

    Whitespace in XML text is preserved.

    Do this instead

    Use .strip() when the extracted text needs whitespace cleaned.

Practice Check

EASY

Suppose an XML string has a person root, a name child containing Ada, and an email child with hide="no". Write the three operations that parse the string, retrieve the name text, and retrieve the hide attribute.

Hints
  • Use ET.fromstring() for the conversion.
  • Use find('name') and then .text for the name.
  • Use find('email') and then .get('hide') for the attribute.
  1. 1
    A reliable sequence is: parse the XML string with ET.fromstring(), use find() to retrieve the first matching element, use .text for content, and use .get(attribute_name) for attributes. Remember that the result of parsing is a hierarchical Element object, and that XML whitespace remains present unless you clean it with .strip().

Key Takeaways

  • ET.fromstring() converts an XML string into a tree of Element objects.
  • The returned root Element represents the outermost XML element and its hierarchy.
  • find() searches for the first element matching a tag name.
  • Use .text for element content and .get(attribute_name) for attribute values.
  • XML whitespace is preserved, so use .strip() when cleaned text is needed.

More concepts starting with P