šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

Processing XML Files in Python

ElementTree for parsing and building XML — still the format of choice for many enterprise APIs, legacy systems, and document formats like SVG and RSS.

⚔ Total XP: 0|šŸ’» python XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Core logic.

Quick Quiz //

For <book id="bk101"><title>The Great Novel</title></book>, how do you access "bk101" versus "The Great Novel"?


šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

XML has fallen out of fashion relative to JSON for new APIs, but it remains the format for SOAP APIs, many enterprise integrations, RSS/Atom feeds, SVG, and countless legacy systems still in production. This lesson covers xml.etree.ElementTree, the standard library's XML toolkit.

1Why XML Still Matters in Professional Python Work

JSON has largely won the popularity contest for new, greenfield APIs — it's more compact, has a simpler specification, and maps more directly onto common programming language data structures. But an enormous amount of software already in production, and a specific set of domains, remain XML-based: SOAP APIs (still common in enterprise, banking, and government integrations), many legacy enterprise systems that predate JSON's dominance, configuration formats for major tools (Maven's pom.xml, Android's layout files), and entire document formats built on XML — SVG, RSS/Atom feeds, and the underlying format inside .docx/.xlsx files (which are actually ZIP archives containing XML, tying directly into the next lesson).

A professional Python developer working on integration code, enterprise software, or anything touching a sufficiently established system will encounter XML with real regularity, regardless of how much new API design has shifted toward JSON — treating XML as obsolete or unnecessary to learn leaves a genuine, common integration surface unaddressed.

xml.etree.ElementTree (commonly imported as ET), in the standard library since 3.3 (no external dependency required, unlike YAML), is the standard, lightweight tool for both parsing existing XML and constructing new XML documents — this lesson's baseline toolkit for professional XML work.

āœ•
—
+
import xml.etree.ElementTree as ET

tree = ET.parse("catalog.xml")
root = tree.getroot()

for book in root.findall("book"):
    title = book.find("title").text
    price = book.find("price").text
    print(f"{title}: ${price}")
localhost:3000
Real-World Prevalence
SOAP, RSS, SVG, .docx internals, enterprise legacy systems
All XML, all still in active production use

2Navigating a Parsed Tree: Elements, Children, Attributes, and Text

ET.parse("catalog.xml").getroot() returns the tree's root Element, and .find(tag)/.findall(tag) — using a simplified, XPath-inspired query syntax — locate a single matching child element or all matching child elements, respectively. root.findall("book") returns every direct <book> child of the root; more elaborate paths like ".//title" (searching recursively at any depth) are also supported for more complex document structures.

A single XML element can carry two genuinely different kinds of data simultaneously, and it's essential to know which access pattern applies to which: attributes — the key="value" pairs written inside an element's opening tag (id="bk101", category="fiction") — are read with .get(attribute_name), returning the attribute's string value or None if it isn't present. Child element text content — the text between an element's opening and closing tags, like The Great Novel inside <title>...</title> — is read via .find(child_tag).text on the parent, first locating the child element and then reading its .text property.

Conflating these two access patterns is a common source of confusion for developers newer to XML specifically because JSON has no equivalent distinction — every value in JSON is 'just a value' at some key, while XML elements genuinely have two separate, co-existing places data can live, and reading the wrong one (trying .get("title") on book instead of .find("title").text) simply returns None rather than raising an obviously diagnosable error.

āœ•
—
+
# <book id="bk101" category="fiction">
#   <title>The Great Novel</title>
# </book>

book_id = book.get("id")           # 'bk101' -- an attribute
category = book.get("category")     # 'fiction' -- another attribute
title = book.find("title").text     # 'The Great Novel' -- child element's TEXT
localhost:3000
Attributes vs Element Text
book.get("id") → attribute
book.find("title").text → child element's text

3Building XML From Scratch: Element and SubElement

Constructing a new XML document programmatically mirrors the reading API's shape: ET.Element("catalog") creates a standalone root element; ET.SubElement(root, "book", id="bk101") creates a new child element attached directly to root, with any keyword arguments (id="bk101") becoming that new element's attributes, and returns the newly-created element so you can immediately continue building on it — setting its .text, or creating further SubElements nested inside it.

ET.tostring(root, encoding="unicode") serializes the fully-constructed tree back into actual XML text — the encoding="unicode" argument specifically requests a Python str result rather than the function's default of returning bytes, which matters when you intend to further process, log, or embed the XML string directly in Python code rather than write it straight to a binary file handle.

This programmatic construction pattern — build a tree of Element/SubElement objects, then serialize once at the end — is the standard approach for generating XML output from Python data (converting a list of Python objects into an XML export, for instance), and it mirrors the same 'build a data structure, serialize once' philosophy used throughout this section for JSON and YAML: manipulate structured, native Python objects throughout your logic, and only convert to the final text format as the very last step.

āœ•
—
+
import xml.etree.ElementTree as ET

root = ET.Element("catalog")
book = ET.SubElement(root, "book", id="bk101")
ET.SubElement(book, "title").text = "The Great Novel"
ET.SubElement(book, "price").text = "29.99"

xml_string = ET.tostring(root, encoding="unicode")
print(xml_string)  # '<catalog><book id="bk101"><title>The Great Novel</title>...'
localhost:3000
Programmatic XML Construction
ET.SubElement(book, "title").text = "..."
Build the tree, serialize once with tostring()

4Step-by-Step Breakdown

JSON won the new-API popularity contest, but XML runs an enormous amount of the enterprise and legacy software you'll eventually need to integrate with. Let's parse and build it correctly.

ElementTree.parse() reads an XML file into a navigable tree -- .find() and .findall() use XPath-like expressions to locate elements.

Attributes (not just text content) are accessed via .get() -- XML elements can carry BOTH child elements AND attributes simultaneously.

Checkpoint: For <book id="bk101"><title>The Great Novel</title></book>, how do you access "bk101" versus "The Great Novel"?

  • →book.get("id") for the attribute "bk101"; book.find("title").text for the child element's text content
  • →Both are accessed the same way, via .text

Building XML from scratch uses Element/SubElement -- and ET.tostring() serializes the tree back to actual XML text.

Checkpoint: What does ET.SubElement(book, "title") do?

  • →Creates a new child element named "title" under the book element, and returns it
  • →Searches for an existing "title" child element under book

XML rounds out the structured-text formats; ZIP Files shifts to binary archive handling.

Navigate Real XML. Finish get_child_text(): find(tag).text pulls out a child element's text content.

Level Up šŸš€

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported (via server-side Python execution).

FirefoxSupported

Fully supported (via server-side Python execution).

SafariSupported

Fully supported (via server-side Python execution).

EdgeSupported

Fully supported (via server-side Python execution).

Best Practices

Know the difference between an element's attributes (.get()) and a child element's text (.find().text)

These are two genuinely different places data lives in XML — conflating them silently returns None rather than raising an obvious error, making the distinction worth internalizing deliberately.

Build XML programmatically with Element/SubElement rather than string concatenation

String-templating XML by hand risks malformed output (unescaped special characters, mismatched tags) that ElementTree's API guarantees is well-formed by construction.

Frequent Bugs

THE BUG

Calling .get('title') on an element expecting to retrieve a child element's TEXT content, when 'title' is actually a child element (not an attribute), silently getting None instead of the expected value.

THE FIX

Use .find("title").text for a child element's text content, and .get("attribute_name") only for genuine attributes written inside the opening tag.

Real-World Examples

Parsing an RSS Feed

A content aggregator needs to parse an RSS feed (an XML format) to extract each article's title, link, and publication date.

import xml.etree.ElementTree as ET

tree = ET.parse("feed.xml")
root = tree.getroot()

for item in root.findall(".//item"):
    title = item.find("title").text
    link = item.find("link").text
    pub_date = item.find("pubDate").text
    print(f"{title} ({pub_date}): {link}")

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Calling .get('child_tag_name') expecting to retrieve a child element's text content, when 'child_tag_name' is actually a nested element rather than an attribute, silently getting None.

# Wrong: 'title' is a child ELEMENT, not an attribute -- silently returns None title = book.get("title") # Correct: access the child element's text content title = book.find("title").text

The Solution //

Use .find("child_tag_name").text to retrieve a child element's text content; reserve .get() specifically for genuine attributes written inside the element's own opening tag.

Lesson Glossary

[01]xml.etree.ElementTree

Python's standard library module for parsing and constructing XML documents.

Code Preview
// xml.etree.ElementTree context

[02]Element

An ElementTree object representing a single XML tag, which can have attributes, text content, and child elements.

Code Preview
// Element context

[03]Attribute (XML)

A key="value" pair written inside an XML element's opening tag, accessed via element.get(key).

Code Preview
// Attribute (XML) context

[04]SubElement

An ElementTree function that creates and attaches a new child element to a given parent element.

Code Preview
// SubElement context

Continue Learning