Python xml.etree.ElementTree: Parsing and Building XML

The xml.etree.ElementTree module is Python's standard, built-in library for handling XML data through a hierarchical, tree-based structure. It provides an efficient and lightweight API designed to both parse existing XML files or strings into navigable Python objects and construct entirely new XML hierarchies from scratch. This article explains how ElementTree operates, covering tree traversal, node creation, attribute management, and document serialization.

Understanding the ElementTree Model

In xml.etree.ElementTree, an XML document is represented as a tree structure consisting of two primary types:

Because an Element acts like a standard Python list regarding its children, child nodes can be accessed directly using indexing, slicing, or iteration.

Parsing XML Documents

The module provides two primary entry points for parsing: parse() for files and fromstring() for in-memory strings.

import xml.etree.ElementTree as ET

# Parsing from a string
xml_data = """<library>
    <book id="1">
        <title>Python Fundamentals</title>
        <author>Jane Doe</author>
    </book>
</library>"""

root = ET.fromstring(xml_data)

# Parsing from a file
# tree = ET.parse("library.xml")
# root = tree.getroot()

Once parsed, elements can be searched using built-in methods that support basic XPath expressions:

for book in root.findall("book"):
    book_id = book.attrib.get("id")
    title = book.find("title").text
    print(f"Book ID: {book_id}, Title: {title}")

Building XML Hierarchies

ElementTree allows programmatic creation of XML hierarchies using the Element and SubElement classes.

  1. Create the Root: Instantiate a top-level node with ET.Element("tag_name").
  2. Append Children: Use ET.SubElement(parent, "tag_name") to automatically instantiate and attach child elements to a parent.
  3. Assign Content: Populate node text using the .text property and attributes using .set("key", "value") or the .attrib dictionary.
import xml.etree.ElementTree as ET

# Create the root node
catalog = ET.Element("catalog")

# Add a child element
item = ET.SubElement(catalog, "item")
item.set("sku", "A123")

# Add sub-elements with text
name = ET.SubElement(item, "name")
name.text = "Wireless Mouse"

price = ET.SubElement(item, "price")
price.text = "29.99"

Modifying Existing Trees

Nodes can be updated, relocated, or deleted dynamically:

Serializing and Writing XML

To export the hierarchy back to raw XML, use ET.tostring() for strings or the write() method on an ElementTree object for file storage.

# Convert the hierarchy to an ElementTree wrapper
tree = ET.ElementTree(catalog)

# Write to a file with XML declaration
tree.write("catalog.xml", encoding="utf-8", xml_declaration=True)

# Generate a string representation
raw_xml = ET.tostring(catalog, encoding="utf-8").decode("utf-8")

Practical Considerations