leptris 1.4.0

Rust bindings for libleptris — fast XML 1.0 parsing, XPath 1.0, SAX
Documentation

leptris (Rust)

Idiomatic Rust bindings for libleptris — pure-C99 XML 1.0 parsing, a W3C-conformant XPath 1.0 engine, and SAX.

Linking

The crate links against a prebuilt libleptris shared library:

# Build the C library once (from the repository root):
cmake -B build-shared -S . -DCMAKE_BUILD_TYPE=Release \
  -DLEPTRIS_BUILD_SHARED=ON -DLEPTRIS_BUILD_STATIC=OFF \
  -DBUILD_TESTING=OFF -DLEPTRIS_BUILD_CLI=OFF
cmake --build build-shared

# Then build/test the crate against it:
LEPTRIS_LIB_PATH=build-shared/src cargo test --manifest-path bindings/rust/Cargo.toml

LEPTRIS_LIB_PATH accepts the library file or its directory. Without it the crate falls back to the system linker search (-lleptris).

Usage

use leptris::{Document, XPathNodeKind};

let doc = Document::parse(b"<catalog><book id='b1'><title>Alpha</title></book></catalog>")?;
let root = doc.root().unwrap();
assert_eq!(root.name(), "catalog");

for book in root.children() {
    println!("{} — {}", book.attribute("id").unwrap(), book.child("title").unwrap().text().unwrap());
}

let hits = doc.xpath("//book[@id='b1']/title")?;
assert_eq!(hits.element(0).unwrap().text(), Some("Alpha"));

// Mixed nodesets (text, comments, attributes):
let nodes = doc.xpath("//node()")?;
assert_eq!(nodes.kind(1), XPathNodeKind::Element);

SAX with closures:

use leptris::sax;

let mut h = sax::Handler::default();
h.start_element = Some(Box::new(|name, attrs| println!("<{name}> {attrs:?}")));
h.characters = Some(Box::new(|t| print!("{t}")));
sax::parse(b"<r><a>hello</a></r>", &mut h)?;

Layout

Mirrors the Ruby (leptris-ruby) and Python (pyleptris) bindings: a hand-maintained FFI layer (src/ffi.rs) mirroring the public headers, with safe wrappers above it. The FFI drift gate keeps the mirror in sync with the C surface.