Python3 XML 解析

Parsing, namespaces, XPath-like search, and safe handling of untrusted XML.

Intermediate
Key PointsElementTree covers 95% of XML work; never parse untrusted XML with the default parser — XXE and billion-laughs are real.

Parse and Walk

Python
import xml.etree.ElementTree as ET

xml = """<catalog>
  <book id="1"><title>Python</title><price>39.9</price></book>
  <book id="2"><title>Go</title><price>45.0</price></book>
</catalog>"""

root = ET.fromstring(xml)
for book in root.findall("book"):
    print(book.get("id"), book.findtext("title"), book.findtext("price"))

Files and Writing

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

book = ET.SubElement(root, "book", {"id": "3"})
ET.SubElement(book, "title").text = "Rust"
ET.SubElement(book, "price").text = "49.0"

ET.indent(tree, space="  ")        # 3.9+ 美化缩进
tree.write("out.xml", encoding="utf-8", xml_declaration=True)

Namespaces

Namespaced documents use {uri}tag in ElementTree. Register a prefix once so the output stays readable.

Python
NS = {"s": "http://www.w3.org/2005/Atom"}

root.findall("s:entry", NS)
root.findtext("s:title", namespaces=NS)

ET.register_namespace("", "http://www.w3.org/2005/Atom")

Safe Parsing

Bash
pip install defusedxml
Python
from defusedxml import ElementTree as SafeET

root = SafeET.fromstring(untrusted_bytes)   # 禁止 DTD / 实体展开
The default expat parser expands entities, which enables XXE file disclosure and exponential blowups. Always use defusedxml for anything a user uploaded.

Friends & Partners