Expand description
Custom input callbacks for xmlRegisterInputCallbacks — bundle
XSLT stylesheets / RNG schemas inside the binary and serve them
through a user-defined URL scheme (e.g. embed:///foo.xsl).
Custom I/O callbacks for libxml2.
libxml2 routes every URL it loads (XML documents, xsl:import /
xsl:include targets, RelaxNG <include>, DTD external subsets,
etc.) through a chain of registered “input callback” handlers. The
default chain handles file://, http://, ftp://, etc.; an
application can prepend its own handler for a custom URL scheme via
xmlRegisterInputCallbacks.
This module wraps that C API in a safe, closure-friendly surface.
The motivating use case is shipping a single-binary CLI that bundles
XSLT stylesheets / RNG schemas via include_bytes! and serves them
through a synthetic scheme (e.g. embed:///foo.xsl), so xsl:import
chains resolve without ever touching the disk.
use libxml::io;
static MAIN: &[u8] = b"<?xml version=\"1.0\"?>\n<root/>";
io::register_input_callback(
|url| url.starts_with("embed:///"),
|url| match url.strip_prefix("embed:///") {
Some("main.xml") => Some(MAIN.to_vec()),
_ => None,
},
);§Lifetime, threading, order
Closures live for the process lifetime — libxml2 has no per-handler
unregister API. They may run on any thread (hence Send + Sync) and
must not panic: unwinding across the extern "C" trampoline
aborts on Rust 2024+. libxml2 walks callbacks newest-first; the
trampolines snapshot the registry and drop the lock before invoking
a user closure, so a closure that re-enters libxml2 won’t
self-deadlock. If open returns None, libxml2 falls through to
the next handler — including its default file/HTTP loaders.
Functions§
- register_
input_ callback - Register a custom input callback with libxml2.