xpath-eval 0.2.2

A pure-Rust XPath 1.0 expression evaluator, generic over the document model
Documentation
# xpath-eval

A pure-Rust implementation of [XPath 1.0](https://www.w3.org/TR/1999/REC-xpath-19991116/)
— parses an XPath expression and evaluates it against a document.

Generic and standalone — not tied to HTML, XML parsing, Schematron, or any
specific document type. Callers provide their own parsed document via a
trait; this crate only implements the XPath side (expression parsing,
the data model view over the caller's tree, and evaluation).

## Status

Implemented: the lexer/parser, the full location-path/predicate evaluation
core (§2), and the complete XPath 1.0 Core Function Library (§4, all 27
functions, including `id()`). 147 tests pass, `clippy` and `fmt` are clean.

## Example

```rust
use xpath_eval::{Document, EvaluationContext, evaluate, parse};

// A caller brings their own tree, implementing `Node`/`Document` over it —
// this crate never parses or builds one itself. See `Node`'s doc comments
// for what each method must return.
# fn example<D: Document>(doc: &D) -> Result<(), Box<dyn std::error::Error>> {
let expr = parse("//item[@id='42']/name/text()")?;
let ctx = EvaluationContext::new(doc.root());
let result = evaluate(&expr, &ctx)?;
println!("{}", result.to_xpath_string());
# Ok(())
# }
```

`EvaluationContext::new` covers the common case (no variables, no namespace
context). For XPath variables (`$x`) or prefixed name tests (`p:foo`) that
need real namespace resolution, build an `EvaluationContext` directly and
supply a `variables`/`namespaces` lookup hook — see their doc comments.

## Scope and known limitations

- **`id()` needs `Node::is_id_attribute()` to be overridden to do anything
  useful.** The XPath 1.0 data model derives ID-ness from a DTD or schema;
  most `Node` implementations have no such information, so the trait's
  default (`false` everywhere) means `id()` is a real function that simply
  never matches. Override `is_id_attribute()` on your `Attribute`-kind
  nodes if you know which attributes are IDs.
- **Namespace-prefix resolution requires a `namespaces` hook.** Without one
  on `EvaluationContext`, a prefixed name test (`p:foo`) never matches any
  node — it does not fall back to guessing. Supply a resolver hook for
  spec-correct prefix→URI resolution.
- **`following`/`preceding` are full document-order axes** (§2.3): each
  walk touches the potentially-large before/after portion of the whole
  tree, not just nearby nodes. Fine for typical documents; be aware of the
  cost on very large trees.
- Implementing `Node` correctly requires `document_order` to be a genuine
  total order consistent with `children()`/`attributes()`/`namespaces()` —
  see the trait's doc comments for the exact ordering rules (element before
  its namespace nodes before its attribute nodes before its children).

## Installation

```toml
[dependencies]
xpath-eval = "0.2"
```

## License

MIT — see [LICENSE](LICENSE).