oxml
🌐 EN , Change language
llms.txt

Architecture & Trade-offs

Comparing oxml to Rust XML Peers

An honest, technical assessment of architectural trade-offs across quick-xml, roxmltree, xot, xee, and libxml2. When to choose oxml, and when to pick an alternative.

Ecosystem Capability Matrix

Every XML library makes deliberate trade-offs between memory footprint, mutation capability, streaming throughput, and query ergonomics. The table below compares the primary Rust XML libraries as of October 2026.

Capability oxml quick-xml roxmltree xot xee
Primary Model Mutable Arena DOM Pull Parser (Streaming) Read-Only Slice Tree Mutable Arena Tree Read-Only Tree
Memory Safety #![forbid(unsafe_code)] Safe Rust Safe Rust Safe Rust Safe Rust
DOM Mutation O(1) Generational None (Event Stream) None (Read-Only) Arena Mutation None (Read-Only)
XPath Support W3C XPath 1.0 None None (Cursor only) None (Cursor only) W3C XPath 3.1
XML Schema (XSD) Partial (95.2% W3C) None None None None
WebAssembly Native (<220 KB) Supported (Reader) Supported (Read-Only) Supported (Tree) Supported (Engine)
AI Agent (MCP) Native (oxml-mcp) None None None None
Core Dependencies 0 (Parser core) 0 (Minimal) 0 (Minimal) Minimal Minimal

Head-to-Head Deep Dive

1. oxml vs quick-xml

quick-xml strengths: With over 379 million downloads, quick-xml is the performance standard for raw streaming pull-parsing in Rust. Because it does not build an in-memory document tree, it achieves streaming throughputs between 1.2 GB/s and 1.5 GB/s with near-zero heap allocations. If you are processing 50 GB log files, financial transaction streams, or running batch ETL where elements are processed and discarded immediately, quick-xml is the best choice.

Where oxml wins: quick-xml does not provide a DOM, XPath evaluation, or schema validation. If your application needs to locate nodes via XPath expressions (such as //soap:Body//m:GetStockPrice), mutate node attributes, re-order children, or serialize formatted XML, quick-xml requires you to implement your own tree data structures. oxml provides a high-level, generational arena DOM with full XPath 1.0 evaluation out of the box.

2. oxml vs roxmltree

roxmltree strengths: roxmltree (>66M downloads) is an exceptionally mature, read-only XML tree representation. By intentionally forbidding mutation and node insertion, it stores the document as a contiguous array of node descriptors referencing the original input string. Memory consumption is predictably low (typically 1.5x to 2x the raw document size), and document parsing is fast and memory-efficient.

Where oxml wins: roxmltree is strictly read-only. You cannot add children, update text, rename tags, or delete elements. Furthermore, roxmltree does not include an XPath engine; queries must be performed manually using Rust iterator methods (e.g. node.children().filter(...)). oxml combines mutable arena operations with standard XPath 1.0 queries and XSD validation.

3. oxml vs xot

xot strengths: xot is a mutable XML tree library that treats XML namespaces, prefixes, and comments as first-class citizens. Like oxml, it uses an arena allocation pattern to avoid pointer indirection and reference counting cycles.

Where oxml wins: oxml ships as an integrated ecosystem: a pure-Rust XPath 1.0 engine, partial W3C XML Schema validation (xmlschema), WebAssembly bindings, a developer CLI tool, and an MCP server for AI agents, all versioned together without dependency mismatches.

4. oxml vs xee

xee strengths: xee (developed by Paligo) is the premier pure-Rust implementation of W3C XPath 3.1 and partial XSLT 3.0. If you require XPath 2.0 or 3.1 capabilities—including regular expression functions (fn:matches), sequence operations, dynamic maps, arrays, or XSLT transformation templates—xee is the library to choose.

Where oxml wins: oxml targets W3C XPath 1.0 and pairs it with mutable DOM manipulation, partial XSD validation, and cross-platform runtimes (WASM, CLI, MCP). If you do not require XPath 3.1 constructs, oxml provides a unified, zero-unsafe package.

5. oxml vs lxml & libxml2

libxml2 / lxml context: libxml2 is the venerable C library underlying Python's lxml, R's xml2, and PHP's XML extensions. In 2025, libxml2 experienced a maintainer transition that highlighted long-standing security challenges inherent in large legacy C codebases (buffer overflows, integer overflows, memory exhaustion, and use-after-free bugs).

Where lxml wins: Decades of maturity, full XSLT 1.0 support, Schematron, RelaxNG, and complete Python ecosystem integration.

Where oxml wins: Complete memory safety enforced by #![forbid(unsafe_code)] at compile time. Pure Rust ensures that untrusted XML inputs cannot trigger undefined behavior, memory corruption, or remote code execution. oxml compiles cleanly to WebAssembly without Emscripten C runtime shims and provides a native Model Context Protocol (MCP) server for modern AI agent integrations.

When Not to Use oxml — Honestly

We believe engineering honesty builds long-term trust. We explicitly recommend choosing alternative tools under the following conditions:

  1. Multi-Gigabyte Streaming Pipelines: If your input files exceed available RAM or you only need to extract values sequentially without building a DOM, use quick-xml.
  2. Strict Read-Only Document Crawling: If you only need to inspect small-to-medium documents without modifying them or running XPath queries, use roxmltree for minimal memory consumption.
  3. XPath 3.1 and XSLT Transformations: If you require XPath 3.1 functions, sequence comprehension, or XSLT stylesheets, use xee or Saxon.
  4. Exhaustive XSD 1.1 with Complex Redefines: If you depend on edge-case XSD 1.1 features or complex schema redefinitions, use libxml2 or Saxon until xmlschema achieves 100% W3C coverage.