roxmltree
Parse XML into a fast, read-only tree in Rust with zero unsafe code and no dependencies.
Repository Health
Technical Analysis
roxmltree is a Rust crate that parses an XML document into a read-only tree you can traverse and query with idiomatic iterators. It is built specifically for the common case where you only need to read data out of XML rather than mutate it, and it exploits that constraint to deliver aggressive performance and low memory overhead.
The library forbids unsafe code, works in no_std environments, and pulls in only a single dependency (memchr). It preserves node and attribute source positions, resolves namespaces, normalizes attribute values, and closely mimics the parsing behavior of Python’s lxml, making it a dependable choice for tooling that consumes large or standards-sensitive XML.
What You Get
- A
Document::parseentry point that produces a borrowable, read-only XML tree - Iterator-based traversal (
descendants,children,ancestors, sibling walks) over typed nodes - Namespace resolution, entity/character reference expansion, and attribute-value normalization
- Preserved source positions for every node and attribute, plus
no_stdand feature-flag configurability
Common Use Cases
- Extracting data from SVG, XML config, or feed documents without mutating them
- High-throughput parsing of very large XML files where memory overhead matters
- Building higher-level parsers (e.g. serde-roxmltree) on top of a stable read-only tree
Under The Hood
Architecture
Parsing flows through three layers in src/: tokenizer.rs emits low-level XML tokens (built on memchr2 for fast scanning and enforcing the XML character grammar via an XmlCharExt trait), parse.rs assembles those tokens into the document while resolving namespaces and normalizing attribute values, and lib.rs exposes the public tree API. The tree itself is stored as flat Vec<NodeData> and Vec<AttributeData> arenas inside Document, with nodes referencing each other by NodeId (a NonZeroU32) rather than pointers — this arena design (adapted from ego-tree) is what enables cheap traversal and lets element and attribute names stay borrowed from the original input.
Tech Stack
Pure Rust on edition 2021 with a minimum supported version of 1.60. The only runtime dependency is memchr (used with default-features = false so the crate can stay no_std). Cargo features gate std and positions (source-position tracking, which can be disabled to shave 8 bytes per node/attribute). The workspace splits benches into a separate member and excludes internal testing tools.
Code Quality
The crate opens with #![forbid(unsafe_code)], #![no_std], and a battery of missing_docs/missing_debug_implementations warnings, and documents an explicit no-panic guarantee. Test coverage is substantial: roughly 1,900 lines across tests/api.rs, tests/ast.rs, tests/dom-api.rs, and an in-crate tokenizer_tests.rs, exercising the tokenizer, DOM-style access, and AST output. Naming is consistent and lifetime parameters ('a, 'input) are threaded carefully to keep the borrowing model sound.
API Design
The public surface is small and idiomatic: you call Document::parse, then reach for well-named accessors (root_element, tag_name, attribute, text, has_tag_name) and iterators that compose naturally with the standard library. Documentation is thorough — rustdoc examples on most methods, a dedicated docs/parsing.md, runnable examples under examples/, and a tests/dom-api.rs that maps browser/JS DOM idioms onto the Rust API for newcomers. Getting a value out of a document takes only a couple of lines with almost no boilerplate.
Used by 2 apps in this directory
Firecrawl
AI Development · Developer Tools
Turn any website into clean, LLM-ready data with a single API call — no proxy headaches, no scraping complexity.
OpenFang
AI Agents
An open-source "Agent Operating System" built in Rust — a single binary providing a kernel, memory, skills, extensions, and multi-channel runtime for running AI agents, with 1,700+ tests and zero clippy warnings.