Skip to main content

Crate sup_xml

Crate sup_xml 

Source
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

AreaFunctions
Parsingparse_str, parse_bytes (both take &ParseOptions), parse_str_with_recovered, parse_bytes_with_recovered
Namespace resolutionparse_ns_str
Serializationserialize_to_string, serialize_formatted, serialize_with
XPath 1.0XPathContext (reusable), xpath_eval, xpath_str, xpath_bool, xpath_num, xpath_count
Typed serde deserializationde::from_str, de::from_bytes (feature serde)
SecurityParseOptions — 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_dtd defaults to false) and no external entity or DTD is ever retrieved from the network or filesystem unless you explicitly install an ParseOptions::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 (XSD pattern facets, XPath matches/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.
AttrIter
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_attribute on its owning element.
Attrs
Lazy iterator over the attributes of a start tag.
BytesAttr
A single attribute from a start tag, with a zero-copy value when possible.
BytesAttrs
Lazy iterator over the attributes of a start tag, yielding raw byte payloads — see BytesAttr for the shape of each item.
CanonicalizeOptions
Options controlling the canonicalization algorithm.
Catalog
In-memory representation of one or more parsed XML catalog files.
ChainedResolver
Composes multiple resolvers, trying each in order. The first resolver to return either Ok or a non-Refused error wins; Refused falls through to the next resolver.
ChildIter
Iterator over a node’s children.
Document
Document owns a Bump and a pointer to the root Node inside that Bump. The struct is self-referential and the unsafety is contained — see the module-level docs for the safety argument.
DocumentBuilder
Constructs a Document one node at a time. The parser uses this internally; consumers building trees by hand use the same.
FilesystemResolver
Recommended default resolver: loads from filesystem only, refuses anything outside the configured allowed-root directories, optionally consults an OASIS catalog first.
HtmlAttribute
A single attribute on a start tag.
HtmlAttrs
Iterable view over an element’s attributes. Cheap to clone (it’s Copy).
HtmlBytesReader
Bytes-flavoured pull reader. Same as HtmlReader but takes raw bytes — html5ever does lossy UTF-8 decoding internally.
HtmlDoctype
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).
HtmlMeta
HTML-specific document metadata. Set when the document came from parse_html_*; None for XML documents.
HtmlParseOptions
Options for the lenient HTML5 parser.
HtmlReader
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.
HtmlSaxParser
Push-based HTML parser. Caller drives input chunks via feed; the parser dispatches events synchronously into the registered handler as they’re produced.
InMemoryResolver
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 XmlReader plus the bookkeeping needed to produce owned iterator items: a path stack, per-frame sibling counters (so book[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.
NetworkResolver
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.
ParseOptions
Security limits and feature flags for the XML parser.
ParseSelectorError
Error parsing a selector string.
Selector
A parsed selector. Construct with Selector::parse.
SerializeOptions
Options that control how a Document is serialized back to XML text.
StreamParser
Pull-based streaming parser that yields arena-allocated subtrees.
XIncludeOptions
Options for process_xincludes.
XPathBindingsBuilder
Builder + XPathBindings impl for caller-supplied namespaces, variables, and extension functions. Cheap to clone (functions are stored in Arc). Pass &builder (or any &dyn XPathBindings) to super::XPathContext::eval_with.
XPathContext
Reusable XPath context for an arena-allocated ArenaDocument.
XPathOptions
Knobs for the XPath 1.0 lexer + evaluator. Default is strict XPath 1.0 spec conformance; flipping libxml2_compatible relaxes three points where libxml2 historically deviates from the spec:
XmlByteStreamReader
Streaming XML reader that pulls bytes from an io::Read source on demand.
XmlBytesReader
XmlDeclInfo
Captured XML declaration fields (<?xml version="…" encoding="…" standalone="…"?>). Populated by XmlBytesReader during prolog parsing; available via XmlBytesReader::xml_decl after 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 as Cow<'src, str> at the boundary. The conversion is a no-op: bytes are valid UTF-8 by the Scanner’s construction-time invariant.

Enums§

BytesEvent
A streaming XML event with lazy access to its payload.
BytesEventInto
A streaming XML event with attributes already parsed into a caller-owned buffer.
C14nMode
Selects which W3C canonicalization algorithm to apply.
CanonicalizeVisitTarget
What the canonicalize_with visibility predicate is being asked about.
ErrorDomain
Which subsystem raised the error.
ErrorLevel
Severity of the error.
Event
A streaming XML event with lazy access to its payload.
EventInto
A streaming XML event with attributes already parsed into a caller-owned buffer.
HtmlEvent
A tree-construction event emitted by the streaming HTML parser.
IterEvent
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.
NodeKind
Discriminant for Node::kind.
NsDeclIter
Iterator yielded by Node::ns_declarations. Each item is (prefix, href) where prefix is None for the default namespace declaration. The variant in use depends on the build feature flags — callers should treat it as opaque.
OutputCharset
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.
QuirksMode
HTML5 quirks-mode flag set from the DOCTYPE. Only meaningful for HTML documents; XML documents always carry None for Document::html_metadata.
ResolveError
Why a resolver couldn’t deliver the requested bytes.
XPathValue

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§

EntityResolver
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.
HtmlSaxHandler
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 needs start_element).

Functions§

canonicalize_include_all
Predicate that includes every visited target. The default used by canonicalize_to_bytes and canonicalize_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 supplied node is treated as the canonicalization root — no inherited namespace context from its ancestors is included.
canonicalize_to_bytes
Canonicalize an entire arena Document into an in-memory Vec.
canonicalize_with
Stream the canonical form of an entire Document into out.
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_paths and Catalog::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 a Document whose 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. See parse_str_with_recovered for 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 if auto_transcode is on) before parsing.
parse_ns_str
Parse input with XML Namespaces 1.0 processing enabled — resolves xmlns declarations, fills the namespace field on every element and prefixed attribute, validates QName syntax, and rejects undeclared prefixes. Convenience wrapper over parse_str with namespace_aware: true.
parse_str
Parse input into an arena-allocated Document. Uses default ParseOptions.
parse_str_with_recovered
Recovery-mode sibling of parse_str. Returns the (best-effort) parsed Document along with the list of non-fatal errors that recovery mode forgave. When ParseOptions::recovery_mode is false the second element is always empty and the first is the same Result as parse_str would have produced.
parse_xpath
Parse an XPath 1.0 expression string into its AST representation using the default strict options. See parse_xpath_with to opt into libxml2-compatible lexing.
parse_xpath_with
Parse an XPath expression with explicit XPathOptions. Today the only knob that affects parsing is libxml2_compatible, which makes the lexer accept exponent-notation in number literals.
process_xincludes
Process every xi:include element in doc, returning a fresh Document in which each include has been replaced by the resolved content. Operates by deep-copying the original tree into a new arena; doc is left untouched.
serialize_formatted
Serialize an arena Document with pretty-printing (newlines + indentation).
serialize_html_to_string
Serialize an arena Document as 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 as crate::serialize_html_to_string but accepts the arena tree.
serialize_to_bytes
Serialize an arena Document to a compact UTF-8 byte vector.
serialize_to_string
Serialize an arena Document to a compact XML string with default options.
serialize_with
Serialize an arena Document with full control via SerializeOptions.
unescape
Expand the five XML predefined entity references (&amp;, &lt;, &gt;, &quot;, &apos;) and numeric character references (&#NN;, &#xNN;) inside s. Intended for callers using ParseOptions::skip_entity_expansion who want to decode a specific text payload on demand.
unescape_bytes
Expand the five XML predefined entity references (&amp;, &lt;, &gt;, &quot;, &apos;) and numeric character references (&#NN;, &#xNN;) inside s. Intended for callers using ParseOptions::skip_entity_expansion who 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 XPathContext to amortise.
xpath_num
xpath_str
xpath_strings

Type Aliases§

Result
Convenience alias used throughout SupXML — equivalent to std::result::Result<T, XmlError>.