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:
Element: Represents a single node in the XML tree. Each element contains a tag name, a dictionary of attributes, text content, and a list of child elements.ElementTree: Represents the entire XML document, acting as a wrapper around the rootElementto facilitate reading from and writing to disk.
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()Navigating and Searching the Tree
Once parsed, elements can be searched using built-in methods that support basic XPath expressions:
root.iter(tag): Recursively searches the entire tree for all elements matching the specified tag.root.findall(match): Searches only immediate child elements for matching tags or relative paths.root.find(match): Returns the first matching element found.
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.
- Create the Root: Instantiate a top-level node with
ET.Element("tag_name"). - Append Children: Use
ET.SubElement(parent, "tag_name")to automatically instantiate and attach child elements to a parent. - Assign Content: Populate node text using the
.textproperty and attributes using.set("key", "value")or the.attribdictionary.
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:
- Update Text/Attributes: Directly reassign
element.text = "new value"or callelement.set("attr", "new value"). - Remove Elements: Use
parent.remove(child)to detach a node from the hierarchy.
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
- Performance: The default C-implementation
(
_elementtree) runs under the hood, making standard operations fast and memory-efficient. - Security: Like many standard XML parsers,
xml.etree.ElementTreeis vulnerable to maliciously crafted XML data (such as entity expansion attacks). For untrusted inputs, use third-party alternatives such asdefusedxml.