libxml-rs 0.1.0-alpha.17

Native-Rust forensic reimplementation of libxml2+libxslt with C ABI drop-in replacement. Cross-version oracle matrix (libxml2 2.7.8-2.15.3, libxslt 1.1.26-1.1.45) with semantic epochs correlated to upstream commits; full xmllint/xmlcatalog/xsltproc CLIs; differential-court-verified C API closure (xmlXPath*, xmlTextReader*, xmlTextWriter*, catalogs, serialization, data globals, chvalid, encoding, the full libxslt surface) — parity ledger at 0 missing for both libxml2 and libxslt. 1135 tests passing.
Documentation

libxml-rs

Phase 11: Historical matrix — semantic epochs for libxml2/libxslt behavior.

Custodial native-Rust reimplementation of the libxml2 + libxslt ecosystem: a forensic reconstruction of observable behavior, implemented in native Rust, with C ABI compatibility for drop-in replacement.

This is not an XML crate. This is not an XSLT crate. This is not a wrapper. This is a custodial forensic archive and native-Rust reimplementation of the complete observable behavior of libxml2 and libxslt across their historical lifetimes.


Current Status: Phase 11 — Historical matrix (§85)

Phase 11 delivers the cross-version archaeology of §41 (historical oracle matrix), §42 (version fingerprints), §51 (multi-version triangulation). Per §85:

Deliverable: The project can explain how current behavior came to exist.

A configurable oracle matrix (oracle/historical/) builds 12 historical libxml2 releases (2.7.8 → 2.15.0) plus 5 libxslt releases (1.1.26 → 1.1.42) from the archaeology git clones and runs a 28-case behavioral corpus against every oracle and the system 2.15.3/1.1.45 binaries, capturing byte-exact stdout/stderr/exit and per-version sha256 fingerprints:

  • oracle/historical/build.sh — era-tolerant oracle builder (era tag spellings, autotools modernizations, --without-threads for modern glibc)
  • oracle/historical/run_matrix.sh — matrix runner + per-case epoch grouping; results/matrix.json holds version→case→sha256
  • atlas/SEMANTIC_EPOCHS.md — the epoch map: 10 behavioral epochs (E-001…E-008 + exit-code epochs) correlated with the exact upstream commits/NEWS that created them
  • courts/suites/historical/HIST-EPOCH-*.json — §43 casefiles; courts/receipts/historical-matrix-2026-08-29.json — §44 receipt

Headline findings (all correlated to upstream commits in the atlas):

  • xmllint --xpath node-set output gained newline separators in 2.9.10 (commit da35eeae, an upstream-documented breaking change)
  • The 2.9.10 parser regression (EndTag: '</' not found) was fixed in 2.9.11 (de5b624f); the second parse-error diagnostic was dropped entirely in 2.12
  • A 2.13.0 cluster: parser/validation exit codes reworked (1→4, 4→3), entity-in-attribute errors reported twice, entity-decl debug nodes became TEXT compact (8d04f0ee)
  • 2.15.0: --html dumps became single-line (newline writes removed from HTMLtree.c); --valid with no DTD returns exit 0
  • libxslt core transform output is a stable epoch — byte-identical from 1.1.26 (2009) to 1.1.45

Phase 10 (historical)

Phase 10 delivered the xmllint and xmlcatalog command-line tools (§36):

Both tools are faithful native-Rust ports of the upstream programs, verified byte-for-byte against the system libxml2 2.15.3 binaries:

  • xmllint CLI--debug, --copy, --format, --valid/--postvalid, --dtdvalid, --xpath/--xpath0, --xinclude, --html/--xmlout, --noent, --no-compact, --encode, --recover, --dropdtd, --pedantic, --noout, --quiet, --nonet, --huge, … with upstream exit codes (0/1/3/4) and the upstream file:line: parser error : MSG + source-line/caret diagnostics
  • xmlcatalog CLI--create, --add, --del, --resolve (system/public/URI), --noout, --shell (interactive resolve/system/public/add/del/dump/help/exit), SGML→XML catalog conversion, upstream exit codes
  • Compact text nodes — the parser reproduces libxml2's XML_PARSE_COMPACT inline text storage (≤15 bytes in the node struct), so --debug dumps show TEXT compact exactly like the oracle; merged/entity-interrupted text is correctly non-compact
  • DTD validation diagnostics--valid output (messages, caret placement, exit codes) matches the oracle for both no-DTD and declaration errors
  • Entity expansion--noent re-parses declared-entity content through the input stack (nested references and markup entities included), matching upstream trees
  • HTML serialization — meta-charset insertion, upstream formatting rules (p/pre/param never formatted, single-child and inline elements inline), HTML document headers
  • 1110 passing tests: cargo test --lib — 0 failures
  • Differential oracle parity: a 44-case CLI suite (target/difftest_summary.sh) is byte-identical to the system tools (stdout + stderr + exit codes), plus a 30+ case edge corpus (entities, DTDs, HTML, compact/no-compact, debug dumps, XPath)

Phase 9 (historical)

Phase 9 delivered the complete EXSLT module set (§35) and the xsltproc command-line tool (§36):

All seven EXSLT modules are implemented natively and registered through the process-wide EXSLT registry (exsltRegisterAll, mirroring upstream):

  • exsl: Commonexsl:node-set (with real result-tree-fragment support), exsl:object-type
  • math:math:max, math:min, math:sin, math:cos, math:tan, math:constant, math:power, math:sqrt, math:log, math:random, …
  • set:set:difference, set:intersection, set:distinct, set:has-same-node, set:leading, set:trailing
  • str:str:tokenize, str:padding, str:concat, str:split, str:replace, str:align, str:encode-uri, str:decode-uri
  • dyn:dyn:evaluate, dyn:element, dyn:attribute, dyn:map, dyn:call, …
  • date:date:date-time, date:date, date:time, date:year, date:month-in-year, date:day-in-month, date:day-of-week-in-month, date:format-date, date:add, date:difference, date:seconds, date:day-name, …
  • func:func:function, func:result (extension-function declarations)
  • exsltRegisterAll C ABI export — mirrors upstream; xsltproc calls it at startup
  • xsltproc CLI — full option surface (--param, --stringparam, --output, --noout, --html, --encoding, --xinclude, --profile, --maxdepth, --maxvars, --nonet, --nowrite, …) with upstream exit codes (1–11)
  • RTF support — variables with inline content become context-owned result tree fragments; exsl:node-set($var)/path navigation works
  • 1110 passing tests: cargo test --lib — 0 failures
  • Differential oracle parity: a 12-case xsltproc corpus (basic transform, count()/AVTs, exsl:node-set/math:/set:/str:, predicates, attribute string-values, xsl:if/xsl:when, numbering, descending xsl:sort, key(), call-template with params, method="html") is byte-identical to the system libxslt 1.1.45 xsltproc (stdout + exit codes)

Underlying subsystem fixes landed during Phase 9

Fix Surface Detail
XPath core functions in XSLT xslt The transform context now registers the XPath 1.0 core function library — before, every XPath function call (count(), substring(), …) failed as unknown
AVT evaluation xslt {expr} attribute value templates evaluated in literal attributes and xsl:element/xsl:attribute/xsl:processing-instruction names (XSLT 1.0 §7.6.2)
RTF variable ownership xslt Inline variable content is deep-copied into a context-owned RVT (freed exactly once at context teardown) — fixes a double-free and enables exsl:node-set
Node string-value tree node_get_content concatenates all descendant text (XPath 1.0 string-value), not just direct text children
Caller parameter format xslt xsltApplyStylesheet params parsed as upstream (name, value) pairs with {uri}name namespace form
date: no-arg default exslt date:date()/date:time() and the component functions default to the current date-time (EXSLT spec)

Phase 8 (historical)

Phase 8 implemented the complete native-Rust XSLT 1.0 engine: stylesheet compilation, template matching, pattern compilation, variable/parameter binding, keys, sorting, numbering, imports/includes, extensions, security, serialization, and the transform runtime (§31–§34). The XSLT engine operates exclusively on the Rust libxml implementation — no upstream libxml2/libxslt is loaded, linked, or shelled out to (§31):

Rust CLI → Rust libxslt compatibility layer → Rust XSLT engine
        → Rust XPath implementation → Rust libxml tree/parser/serializer

Subsystem fixes landed during Phase 8:

Fix Surface Detail
SAX2 namespace resolution parser startElementNs receives split prefix/localname + resolved URIs; element and attribute namespaces now attached by the tree builder
Absolute path evaluation XPath /root/item evaluates from the document node, not the root element (XPath 1.0 / semantics)
XPath C ABI helpers ABI xmlXPathObjectCopy, xmlXPathCastToString, xmlXPathCastStringToNumber, xmlXPathCmpNodes, xmlXPathNodeSetCreate
Node content getter tree node_get_content (upstream xmlNodeGetContent semantics)
Template-content ownership xslt Template content belongs to the stylesheet document; xsltFreeTemplate no longer double-frees it
node()/text() patterns xslt Bare node-test calls translate to steps with correct §5.5 priorities
match="/" semantics xslt Matches only the document node, not the root element

All six Phase 8 residuals are documented in atlas/RESIDUAL_LEDGER.md (R-000101–R-000106).

Build

cargo build                          # Build library + CLI binaries
cargo build --lib                    # Build only the library
cargo test --lib                     # Run library tests (1110 passing)

# Test C consumer compilation against our headers:
gcc -I include courts/suites/sanity/ABI-STRUCT-NODE-0001-abicheck.c -o /tmp/abicheck
clang -I include courts/suites/sanity/ABI-ENUM-0001-enumcheck.c -o /tmp/enumcheck

# Build and run oracle container:
docker build -f docker/Dockerfile.oracle -t libxml-rs/oracle:2.12.0 docker/

Published artifacts

Oracle verification

The oracle Docker container builds libxml2 2.12.0 and libxslt 1.1.39 from source. The candidate (libxml-rs) does not link against system libxml2/libxslt — verified by the oracle contamination court.


Test coverage by subsystem

Subsystem Tests Subsystem Tests Subsystem Tests
XPath 1.0 128 URI 69 Encoding 65
XML Schema (XSD) 62 DTD validation 56 RELAX NG 56
XML parser + SAX 50 Regex 44 I/O 44
Schematron 40 DTD 35 XML Reader 35
Entities 31 HTML 31 C14N 29
Tree/ownership 28 XInclude 23 XML Writer 20
Automata 16 Catalog 16 XPointer 15
Debug 11 Hash 9 List 8
Dictionary 7 Globals 7 String 6
Errors 5 Memory 2 Threads 2
ABI allocator 8
XSLT patterns 46 XSLT transform 26 XSLT security 7
XSLT numbering 5 XSLT stylesheet 4 XSLT variables/params 9
XSLT compiler 3 XSLT sorting 3 XSLT misc (keys/space/serial/ns/imports/ext) 13
EXSLT dates 9 EXSLT strings 6 EXSLT math 5
EXSLT common 4 EXSLT sets 4 EXSLT dynamic 2
EXSLT functions 1 EXSLT registry 3 XSLT params 5
Total (1110 passing, 1 ignored)

Project Structure

libxml-rs/
├── Cargo.toml              # Single Cargo package (no workspace)
├── src/
│   ├── lib.rs              # Library entry point
│   ├── abi/                # C ABI compatibility layer (§4, §14)
│   ├── xml/                # libxml2 implementation (§1, §3, §31)
│   ├── xslt/               # libxslt implementation (§31–§34)
│   ├── exslt/              # EXSLT modules (§35)
│   ├── compatibility/      # Historical profiles, quirks, platform (§68, §69)
│   └── bin/                # CLI tools: xmllint, xmlcatalog, xsltproc (§36)
├── include/                # Compatible C headers (§15)
├── atlas/                  # Forensic archive (§7–§12)
│   ├── releases/           # Release manifests per version
│   ├── api/                # Public API inventories
│   ├── abi/                # ABI snapshots
│   ├── symbols/            # Symbol table comparisons
│   ├── config/             # Build configuration profiles
│   ├── standards/          # Standards mapping
│   ├── HISTORY.md          # Complete release history
│   ├── LORE.md             # Undocumented behavior archive
│   ├── QUIRKS.md           # Confirmed compatibility quirks
│   ├── PARITY_MATRIX.md    # Current parity status
│   ├── RESIDUAL_LEDGER.md  # Unexplained differences
│   └── SECURITY_HISTORY.md # Vulnerability custody
├── oracle/                 # Reproducible upstream build environment (§39)
├── courts/                 # Differential testing framework (§40–§50)
│   ├── schema.json         # Casefile schema
│   ├── suites/             # Court case suites
│   ├── receipts/           # Execution receipts
│   └── tools/              # Court runner
├── tools/                  # Archaeology and analysis tooling
│   ├── archaeology/        # manifest.py, apiatlas.py, symbols.py, delta.py, profileconfig.py
│   └── courts/             # Court runner
├── docker/                 # Reproducible Docker oracle images
├── docs/                   # Technical documentation
└── archaeology/            # Upstream git clones (immutable, offline)

Build

cargo build              # Build the library and CLI binaries
cargo build --lib        # Build only the library
cargo test --lib         # Run library tests (1110 passing)
cargo build --release    # Optimized build (LTO, panic=abort)

The crate builds as cdylib + staticlib + rlib; the build script also emits libxml-2.0.pc/libxslt.pc pkg-config files, xml2-config/xslt-config scripts, and SONAME symlinks into the target directory.


License

Licensed under either of:

at your option.


Project Status

Dimension Status
API completeness 🟢 libxml2 surfaces complete; libxslt ABI (33 symbols) exported
ABI compatibility 🟢 ABI courts passing (struct, symbol, enum)
Tree/ownership 🟢 28 tree tests passing
XML parser + SAX 🟢 50 parser tests; SAX2 namespace resolution
XPath 1.0 🟢 128 tests, absolute paths, node sets, conversions
Validation family 🟢 DTD (56) + XSD (62) + RELAX NG (56) + Schematron (40)
XSLT 1.0 engine 🟢 103 tests; full instruction surface; end-to-end transforms
C headers 🟢 45+19 headers, gcc & clang, zero warnings
CLI parity 🟢 xsltproc (Phase 9), xmllint + xmlcatalog (Phase 10) complete with upstream exit codes and differential oracle parity
EXSLT 🟢 All seven modules registered (34 tests); exsl:node-set on RTFs, math/set/str/dyn/date/func verified end-to-end
Historical atlas 🟢 Semantic epochs (E-001…E-008) + release manifests + API/ABI snapshots; atlas/SEMANTIC_EPOCHS.md correlates every behavior change with its upstream commit
Oracle infrastructure 🟢 Docker oracle built and verified; 12 historical libxml2 + 5 libxslt oracles built from archaeology git with era-tolerant build tooling (oracle/historical/)
Court coverage 🟢 ABI courts passing; differential suites staged
Downstream testing 🔴 Not started (Phase 12)

See atlas/PARITY_MATRIX.md for the detailed, evidence-bounded parity matrix and atlas/RESIDUAL_LEDGER.md for the residual ledger.