pugixml's C++ DOM, an inlined yxml streaming parser, and Cython
holding them together — dictify,
objectify,
jsonify, and a CLI.
pip install pygixml
API reference and guides on one side, honest performance numbers — refreshed on a schedule, not hand-edited — on the other.
Pick the layer that matches what you're actually doing with the file, not one generic tree API forced onto every use case.
xmltodict — drop-in, not a rewrite.root.child.grandchild — nothing materialized until touched.stream_dump — flat memory, however big the file gets.iterparse / iterfind over yxml — process a file too big to ever load whole, one element at a time.pygixml cat, query, stream, convert — XML from a shell pipeline.Speed and memory aren't the whole story, and pygixml's scope isn't either — it's a Python Giant XML framework, built on pugixml plus a streaming yxml layer for the oversized case. A factual capability comparison, not a benchmark; static, so it lives here rather than in the generated report.
| Feature | pygixml | lxml | ElementTree | xmltodict | xmljson |
|---|---|---|---|---|---|
|
XPath queries
Selecting nodes with an XPath expression.
|
✓ Full XPath 1.0 (via pugixml) |
✓ Full XPath 1.0, plus EXSLT extensions |
~ Small subset: no position(), limited axes |
✗ | ✗ |
XSLT transforms |
✗ | ✓ via libxslt |
✗ | ✗ | ✗ |
XML Schema (XSD) / DTD validation |
✗ | ✓ via libxml2 |
✗ | ✗ | ✗ |
|
Streaming, item-by-item parse
Process one element at a time without holding the whole tree.
|
✓ iterparse/iterfind (yxml-based) |
✓ iterparse |
✓ iterparse |
✓ item_depth + item_callback |
✗ needs an already-built tree |
|
Constant-memory XML → single JSON
Converting a file too large for RAM into one valid JSON document.
|
✓ jsonify.stream_dump |
✗ | ✗ | ✗ streams dicts to a callback, not one JSON doc |
✗ |
Built-in XML ↔ dict/JSON conversion |
✓ dictify (xmltodict-compatible) + jsonify |
✗ needs xmljson |
✗ | ✓ its entire purpose |
✓ needs lxml/ElementTree to parse first |
YAML / TOON conversion |
✓ pygixml convert (optional deps) |
✗ | ✗ | ✗ | ✗ |
|
Dotted / attribute-style navigation
doc.root.child.grandchild instead of find()/XPath.
|
✓ objectify |
✓ lxml.objectify |
✗ | ✗ plain dict access only |
✗ |
Command-line tools |
✓ cat, query, jsonify, stream, convert |
✗ | ✗ | ✗ | ✗ |
Backend |
✓ C++ (pugixml + inlined yxml) via Cython |
✓ C (libxml2 / libxslt) |
~ C accelerator, pure-Python fallback |
✗ pure Python, over stdlib expat |
✗ pure Python |
Standard library (zero install) |
✗ | ✗ | ✓ | ✗ | ✗ |
|
abi3 / stable-ABI wheels
One compiled wheel across Python minor versions.
|
✓ cp310-abi3, covers 3.10+ |
✗ per-Python-version wheels |
✓ n/a — ships with the interpreter |
✓ n/a — pure Python |
✓ n/a — pure Python |
The same document, four ways.
import pygixml
doc = pygixml.parse_string("<root><item id='1'>a</item></root>")
root = doc.root()
print(root.child("item").attribute("id").value()) # 1
One pip install, no compiler needed on the common platforms.