name: processing-xml description: Creates, reads, modifies, validates, and queries XML files with Python. Use when the user asks to parse, edit, generate, validate, or extract data from an .xml file, mentions XML elements, attributes, namespaces, XPath queries, or XSD validation, or needs to transform XML data. Do not use for HTML pages (different parser tolerance) or for the internal XML of .docx/.xlsx/.pptx files (use the corresponding Office skill).
Processing XML
When to use / when NOT to use
- Use for: creating, reading, editing, validating, or querying standalone
.xmlfiles (data feeds, configs, sitemaps, SVG as data, exports). - Do NOT use for: HTML pages (use the HTML skill — HTML parsers tolerate malformed markup, XML parsers do not) or the internal XML inside
.docx/.xlsx/.pptxarchives (use the corresponding Office skill).
Quick reference
Default: stdlib xml.etree.ElementTree (no install). Untrusted input: defusedxml (pip install defusedxml) — same API, blocks entity-expansion attacks. Escape hatch: lxml (pip install lxml) only when you need full XPath 1.0, XSD validation, or pretty-printing on Python ❤️.9.
python
import xml.etree.ElementTree as ET
# Read
tree = ET.parse("data.xml")
root = tree.getroot()
# Query (namespaced documents need an explicit map)
ns = {"a": "http://example.com/ns"}
items = root.findall(".//a:item", ns)
# Modify
for item in items:
item.set("status", "done")
# Write — always preserve the declaration and encoding
tree.write("data.xml", xml_declaration=True, encoding="utf-8")Create:
python
root = ET.Element("catalog")
book = ET.SubElement(root, "book", id="1")
ET.SubElement(book, "title").text = "Example"
ET.indent(root) # pretty-print, Python 3.9+
ET.ElementTree(root).write("out.xml", xml_declaration=True, encoding="utf-8")Rules
- Never regex-edit XML. Parse, modify the tree, re-serialize — always.
- Handle namespaces explicitly with a namespace map; register prefixes before writing to avoid
ns0:pollution. - Always write with
xml_declaration=True, encoding="utf-8"so the declaration survives round-trips.
Workflow
- Identify the operation (create / read / modify / validate / query) and whether input is untrusted (→ defusedxml).
- Parse the file; on
ET.ParseError, report the message with its line/column verbatim and stop — do not guess at fixes. - Perform the operation per the Quick reference (deeper recipes in references/recipes.md).
- Write with declaration + encoding preserved.
- Validate: re-parse the written file (
ET.parse(output)); if an XSD was given, validate against it with lxml. Fix and repeat step 3 until it parses clean.
Edge cases & failure modes
lxml/defusedxmlmissing →pip install lxml/pip install defusedxml; fall back to stdlib ElementTree if the feature allows.- Malformed XML → relay the parser's error (line, column) to the user; never hand-patch text and retry silently.
- Encoding mismatch (declaration says one thing, bytes say another) → parse from bytes, not decoded text; report if it still fails.
- Huge files (>100 MB) → stream with
ET.iterparse(path, events=("end",))andelem.clear()after each record instead of loading the whole tree.
References
Deeper copy-paste recipes (XPath, XSD validation, namespace round-trips, conversion): see references/recipes.md.