Expand description
SupXML — a memory-safe, libxml2-compatible XML library for Rust.
§Quick start
use sup_xml::{parse_str, serialize_to_string, xpath_count, ParseOptions};
let doc = parse_str(r#"
<catalog>
<book id="1"><title>Dune</title></book>
<book id="2"><title>Foundation</title></book>
</catalog>
"#, &ParseOptions::default()).unwrap();
// Navigate with XPath.
assert_eq!(xpath_count(&doc, "/catalog/book").unwrap(), 2);
// Roundtrip back to XML text.
let xml = serialize_to_string(&doc);
assert!(xml.contains("<title>Dune</title>"));§Feature overview
| Area | Functions |
|---|---|
| Parsing | parse_str, parse_bytes (both take &ParseOptions), parse_str_with_recovered, parse_bytes_with_recovered |
| Namespace resolution | parse_ns_str |
| Serialization | serialize_to_string, serialize_formatted, serialize_with |
| XPath 1.0 | XPathContext (reusable), xpath_eval, xpath_str, xpath_bool, xpath_num, xpath_count |
| Typed serde deserialization | de::from_str, de::from_bytes (feature serde) |
| Security | ParseOptions — entity budget, depth limit, external-entity toggle |
§Thread safety
A Document owns its entire arena, so it is Send: you can parse
on one thread and hand the whole document to another for XPath, walking,
or serialization. Parsing itself is thread-independent — every call to
parse_str / parse_bytes builds a self-contained document with no
shared mutable state, so any number of threads can parse concurrently.
use sup_xml::{parse_str, xpath_count, ParseOptions};
let doc = parse_str("<r><a/></r>", &ParseOptions::default()).unwrap();
// Moving the whole document into a thread is fine — `Document: Send`.
let n = std::thread::spawn(move || xpath_count(&doc, "//a").unwrap())
.join()
.unwrap();
assert_eq!(n, 1);A Document is not Sync, however: its nodes thread themselves
together with interior-mutable pointers, so a shared &Document cannot
be touched from two threads at once. Share work by giving each thread its
own document, not a borrow of one.
use sup_xml::{parse_str, xpath_count, ParseOptions};
let doc = parse_str("<r><a/></r>", &ParseOptions::default()).unwrap();
// `&Document` is not `Sync`, so it cannot be shared across scoped
// threads — this fails to compile.
std::thread::scope(|s| {
s.spawn(|| xpath_count(&doc, "//a").unwrap());
s.spawn(|| xpath_count(&doc, "//a").unwrap());
});§Security
SupXML is built to parse untrusted input safely, and the default
ParseOptions are the hardened stance — you opt out of
protections, never into them.
- No external fetches (XXE / SSRF). External DTD loading is off
(
ParseOptions::load_external_dtddefaults tofalse) and no external entity or DTD is ever retrieved from the network or filesystem unless you explicitly install anParseOptions::external_resolver. An unresolved external entity reference is rejected, not silently expanded. - Bounded entity expansion (billion laughs).
ParseOptions::max_entity_expansion_bytes(default 1 MB) caps total expanded entity text, defeating exponential/quadratic blowup. - Bounded nesting (stack-exhaustion DoS).
ParseOptions::max_element_depth(default 256) caps element nesting; DTD content models and regular expressions (XSDpatternfacets, XPathmatches/replace/tokenize) are independently depth-bounded so malicious schemas and patterns cannot overflow the parser stack. - Memory safety by construction. This crate is
#![forbid(unsafe_code)]; the parser cannot produce a buffer overflow or use-after-free regardless of input.
See the Security reference in the SupXML documentation for the full threat model.
Modules§
- async_
io - Async I/O entry points — feature
tokio. - de
- Serde-driven XML deserialization.
- encoding
- Encoding detection and transcoding to UTF-8.
- xpath
- XPath 1.0 + a small subset used for fast streaming-style node matching.
- xsd
- XML Schema 1.0 — schema compiler and instance validator.
- xslt
- XSLT 1.0 transform engine.
Structs§
- Attr
- A single attribute from a start tag, with a zero-copy value when possible.
- Attr
Iter - Iterator over an element’s attributes.
- Attribute
- An attribute on an element. Belongs to a doubly-linked list rooted at
Node::first_attribute/Node::last_attributeon its owning element. - Attrs
- Lazy iterator over the attributes of a start tag.
- Bytes
Attr - A single attribute from a start tag, with a zero-copy value when possible.
- Bytes
Attrs - Lazy iterator over the attributes of a start tag, yielding raw byte
payloads — see
BytesAttrfor the shape of each item. - Canonicalize
Options - Options controlling the canonicalization algorithm.
- Catalog
- In-memory representation of one or more parsed XML catalog files.
- Chained
Resolver - Composes multiple resolvers, trying each in order. The first
resolver to return either
Okor a non-Refusederror wins;Refusedfalls through to the next resolver. - Child
Iter - Iterator over a node’s children.
- Document
Documentowns aBumpand a pointer to the rootNodeinside thatBump. The struct is self-referential and the unsafety is contained — see the module-level docs for the safety argument.- Document
Builder - Constructs a
Documentone node at a time. The parser uses this internally; consumers building trees by hand use the same. - Filesystem
Resolver - Recommended default resolver: loads from filesystem only, refuses anything outside the configured allowed-root directories, optionally consults an OASIS catalog first.
- Html
Attribute - A single attribute on a start tag.
- Html
Attrs - Iterable view over an element’s attributes. Cheap to clone
(it’s
Copy). - Html
Bytes Reader - Bytes-flavoured pull reader. Same as
HtmlReaderbut takes raw bytes — html5ever does lossy UTF-8 decoding internally. - Html
Doctype - Captured DOCTYPE content from an HTML document. Stored verbatim; HTML5 does not validate against DTDs, but the public/system identifiers are surfaced for tools that want to introspect them (e.g. detecting XHTML vs HTML5 input).
- Html
Meta - HTML-specific document metadata. Set when the document came from
parse_html_*;Nonefor XML documents. - Html
Parse Options - Options for the lenient HTML5 parser.
- Html
Reader - Pull-based HTML event reader (XmlReader twin). Iterate events
with
next(); the reader feeds the next 8 KiB chunk into html5ever whenever its internal queue runs dry. - Html
SaxParser - Push-based HTML parser. Caller drives input chunks via
feed; the parser dispatches events synchronously into the registered handler as they’re produced. - InMemory
Resolver - Resolver backed by an in-memory map from system_id to bytes. Refuses anything not in the map. Useful in tests where you want deterministic resolution without filesystem dependencies.
- Iterparse
- Owns an
XmlReaderplus the bookkeeping needed to produce owned iterator items: a path stack, per-frame sibling counters (sobook[2]etc. show up in the path), and an attribute scratch buffer. - Namespace
- A namespace binding (
prefix → href). Lifetime-bound to the document’s arena. - Network
Resolver - HTTPS-fetching resolver. Hardened by default with multiple SSRF and amplification defenses; the constructor requires a host allowlist so there’s no convenient “any host” mode.
- Node
- A node in the XML tree. One struct for every kind; fields are used per-kind.
- Parse
Options - Security limits and feature flags for the XML parser.
- Parse
Selector Error - Error parsing a selector string.
- Selector
- A parsed selector. Construct with
Selector::parse. - Serialize
Options - Options that control how a
Documentis serialized back to XML text. - Stream
Parser - Pull-based streaming parser that yields arena-allocated subtrees.
- XInclude
Options - Options for
process_xincludes. - XPath
Bindings Builder - Builder +
XPathBindingsimpl for caller-supplied namespaces, variables, and extension functions. Cheap to clone (functions are stored inArc). Pass&builder(or any&dyn XPathBindings) tosuper::XPathContext::eval_with. - XPath
Context - Reusable XPath context for an arena-allocated
ArenaDocument. - XPath
Options - Knobs for the XPath 1.0 lexer + evaluator. Default is strict
XPath 1.0 spec conformance; flipping
libxml2_compatiblerelaxes three points where libxml2 historically deviates from the spec: - XmlByte
Stream Reader - Streaming XML reader that pulls bytes from an
io::Readsource on demand. - XmlBytes
Reader - XmlDecl
Info - Captured XML declaration fields (
<?xml version="…" encoding="…" standalone="…"?>). Populated byXmlBytesReaderduring prolog parsing; available viaXmlBytesReader::xml_declafter the first event has been read. - XmlError
- A structured XML processing error.
- XmlReader
- Streaming XML reader with string-typed events. Thin wrapper around
XmlBytesReader— the engine runs in raw bytes and we re-label each event’s payload asCow<'src, str>at the boundary. The conversion is a no-op: bytes are valid UTF-8 by the Scanner’s construction-time invariant.
Enums§
- Bytes
Event - A streaming XML event with lazy access to its payload.
- Bytes
Event Into - A streaming XML event with attributes already parsed into a caller-owned buffer.
- C14n
Mode - Selects which W3C canonicalization algorithm to apply.
- Canonicalize
Visit Target - What the
canonicalize_withvisibility predicate is being asked about. - Error
Domain - Which subsystem raised the error.
- Error
Level - Severity of the error.
- Event
- A streaming XML event with lazy access to its payload.
- Event
Into - A streaming XML event with attributes already parsed into a caller-owned buffer.
- Html
Event - A tree-construction event emitted by the streaming HTML parser.
- Iter
Event - One streamed event. Names, attribute values, and text content
are owned
Strings so the iterator can yield items independent of the reader’s source buffer lifetime. - Node
Kind - Discriminant for
Node::kind. - NsDecl
Iter - Iterator yielded by
Node::ns_declarations. Each item is(prefix, href)whereprefixisNonefor the default namespace declaration. The variant in use depends on the build feature flags — callers should treat it as opaque. - Output
Charset - The charset the serialized bytes will ultimately be encoded into.
Characters the charset cannot represent are emitted as numeric
character references (
&#N;) in text / attribute content, matching libxml2’s serializer: a non-UTF-8 output encoding escapes anything outside its repertoire rather than dropping or mis-encoding it. - Quirks
Mode - HTML5 quirks-mode flag set from the DOCTYPE. Only meaningful for HTML
documents; XML documents always carry
NoneforDocument::html_metadata. - Resolve
Error - Why a resolver couldn’t deliver the requested bytes.
- XPath
Value
Constants§
- DEFAULT_
BUFFER_ SIZE - Default working-buffer size when none is provided. Matches
libxml2’s
XML_MAX_TEXT_LENGTH(10 MB) — bigger than any single text node in the vast majority of real-world XML, small enough that streaming meaningfully saves memory vs slurping. - HUGE_
BUFFER_ SIZE - “Huge” mode buffer size — matches libxml2’s
XML_PARSE_HUGE(1 GB). Use for inputs that contain unusually large tokens (embedded base64 blobs in SVG, OOXML packages, etc.). - XINCLUDE_
NS - XInclude namespace URI. Constant per spec § 4.
Traits§
- Entity
Resolver - Resolves external XML resources by their public/system identifier. Implementors decide what URLs are loadable, where the bytes come from, and what security checks apply.
- Html
SaxHandler - Callback trait for the push-based
HtmlSaxParser. All methods have default no-op implementations — implementers override only the events they care about (e.g. an<a href>extractor only needsstart_element).
Functions§
- canonicalize_
include_ all - Predicate that includes every visited target. The default used by
canonicalize_to_bytesandcanonicalize_node_to_bytes. - canonicalize_
node_ to_ bytes - Canonicalize a single arena node and its descendants into an
in-memory
Vec. The node is treated as the canonicalization root — no inherited namespace context from ancestors is included. - canonicalize_
node_ with - Stream the canonical form of a single subtree into
out. The suppliednodeis treated as the canonicalization root — no inherited namespace context from its ancestors is included. - canonicalize_
to_ bytes - Canonicalize an entire arena
Documentinto an in-memoryVec. - canonicalize_
with - Stream the canonical form of an entire
Documentintoout. - discover_
catalog_ paths - Discover XML catalog files using libxml2-compatible rules.
- load_
default_ catalog - Load a catalog using the default discovery rules — convenience
wrapper combining
discover_catalog_pathsandCatalog::from_files. Silently skips paths that don’t exist (a fresh macOS install, for example, returns an empty catalog). - parse_
bytes - Byte-slice sibling of
parse_str. - parse_
bytes_ in_ place - Destructive-parse fast path. Takes ownership of
buf, mutates it in place during parsing, and returns aDocumentwhose strings point directly into the (now-mutated) buffer. The Document keeps the buffer alive for its lifetime. - parse_
bytes_ ⚠unchecked - Byte-slice version that skips the upfront UTF-8 validation. Mirrors
parse_bytes_unchecked. - parse_
bytes_ with_ recovered - Recovery-mode sibling of
parse_bytes. Seeparse_str_with_recoveredfor semantics. - parse_
html_ bytes - Parse an HTML document from raw bytes into the arena DOM.
- parse_
html_ bytes_ opts - Parse HTML bytes into the arena DOM with explicit options.
- parse_
html_ bytes_ with_ recovered - Bytes equivalent of
parse_html_str_with_recovered. - parse_
html_ str - Parse an HTML document from a UTF-8 string into the arena DOM.
- parse_
html_ str_ opts - Parse an HTML string into the arena DOM with explicit options.
- parse_
html_ str_ with_ recovered - Parse an HTML document from a string, returning both the document and the
list of recovered well-formedness errors. The document is returned even if
errors were recovered; callers can inspect the
Vec<XmlError>to see what was repaired. - parse_
ns_ bytes - Byte-slice sibling of
parse_ns_str. Validates UTF-8 (or auto-transcodes ifauto_transcodeis on) before parsing. - parse_
ns_ str - Parse
inputwith XML Namespaces 1.0 processing enabled — resolvesxmlnsdeclarations, fills thenamespacefield on every element and prefixed attribute, validates QName syntax, and rejects undeclared prefixes. Convenience wrapper overparse_strwithnamespace_aware: true. - parse_
str - Parse
inputinto an arena-allocatedDocument. Uses defaultParseOptions. - parse_
str_ with_ recovered - Recovery-mode sibling of
parse_str. Returns the (best-effort) parsedDocumentalong with the list of non-fatal errors that recovery mode forgave. WhenParseOptions::recovery_modeisfalsethe second element is always empty and the first is the sameResultasparse_strwould have produced. - parse_
xpath - Parse an XPath 1.0 expression string into its AST representation
using the default strict options. See
parse_xpath_withto opt into libxml2-compatible lexing. - parse_
xpath_ with - Parse an XPath expression with explicit
XPathOptions. Today the only knob that affects parsing islibxml2_compatible, which makes the lexer accept exponent-notation in number literals. - process_
xincludes - Process every
xi:includeelement indoc, returning a freshDocumentin which each include has been replaced by the resolved content. Operates by deep-copying the original tree into a new arena;docis left untouched. - serialize_
formatted - Serialize an arena
Documentwith pretty-printing (newlines + indentation). - serialize_
html_ to_ string - Serialize an arena
Documentas HTML5. Emits the DOCTYPE if the document carries one, never emits an XML declaration, uses HTML5 void- element / raw-text / boolean-attribute conventions. Same shape ascrate::serialize_html_to_stringbut accepts the arena tree. - serialize_
to_ bytes - Serialize an arena
Documentto a compact UTF-8 byte vector. - serialize_
to_ string - Serialize an arena
Documentto a compact XML string with default options. - serialize_
with - Serialize an arena
Documentwith full control viaSerializeOptions. - unescape
- Expand the five XML predefined entity references (
&,<,>,",') and numeric character references (&#NN;,&#xNN;) insides. Intended for callers usingParseOptions::skip_entity_expansionwho want to decode a specific text payload on demand. - unescape_
bytes - Expand the five XML predefined entity references (
&,<,>,",') and numeric character references (&#NN;,&#xNN;) insides. Intended for callers usingParseOptions::skip_entity_expansionwho want to decode a specific text payload on demand. - verify_
license - Verify the license now, caching the result, and return an error if no valid, non-expired certificate is present.
- xpath_
bool - xpath_
count - xpath_
eval - One-shot XPath evaluation against an arena document. Builds a fresh
index per call — use
XPathContextto amortise. - xpath_
num - xpath_
str - xpath_
strings
Type Aliases§
- Result
- Convenience alias used throughout SupXML — equivalent to
std::result::Result<T, XmlError>.