1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// SPDX-License-Identifier: MIT OR Apache-2.0
// Copyright (c) 2026 oxml. All rights reserved.
//! # oxml
//!
//! A pure Rust XML toolkit. Zero unsafe code. Parsing, an ergonomic
//! tree, and `XPath` 1.0.
//!
//! ## Why this exists
//!
//! Rust's XML ecosystem is strong at one end and empty at the other.
//! `quick-xml` and `roxmltree` parse quickly; nothing maintained
//! offers what `lxml` gives Python. The only `XPath` crate,
//! `sxd-xpath`, has not shipped a release since 2018, and XSLT and
//! XSD validation have no pure-Rust implementation at all.
//!
//! oxml closes the query gap first, because that is the one people
//! actually hit.
//!
//! ## Quick Start
//!
//! ```
//! # #[cfg(all(feature = "xpath", feature = "std"))] {
//! use oxml::{parse, XPath};
//!
//! let doc = parse(r#"
//! <library>
//! <book lang="en"><title>Dune</title></book>
//! <book lang="fr"><title>Germinal</title></book>
//! </library>
//! "#).unwrap();
//!
//! let titles = XPath::compile("//book[@lang='en']/title").unwrap();
//! let found = titles.evaluate(&doc);
//!
//! assert_eq!(found.to_str(&doc), "Dune");
//! # }
//! ```
//!
//! ## Walking the tree directly
//!
//! `XPath` is optional. The tree stands on its own:
//!
//! ```
//! use oxml::parse;
//!
//! let doc = parse("<a><b id='1'>text</b></a>")?;
//! let root = doc.root_element().expect("a root element");
//!
//! assert_eq!(doc.element_name(root).unwrap().local, "a");
//!
//! let b = doc.children(root)[0];
//! assert_eq!(doc.attribute(b, "id"), Some("1"));
//! assert_eq!(doc.text(b), "text");
//! # Ok::<(), oxml::Error>(())
//! ```
//!
//! ## Design
//!
//! - **Zero `unsafe`** — `#![forbid(unsafe_code)]`, enforced at
//! compile time. The tree is an arena of index-addressed nodes, so
//! parent links cost no `Rc`, no `RefCell`, and no raw pointers.
//!
//! - **No entity expansion** — only the five predefined entities and
//! numeric character references are resolved. External and custom
//! entities are not, which forecloses XXE and billion-laughs by
//! construction rather than by configuration. A parser that cannot
//! expand them cannot be talked into leaking a file.
//!
//! - **Namespace-correct** — names compare by URI and local part,
//! never by prefix. An unprefixed *element* takes the default
//! namespace; an unprefixed *attribute* is in no namespace. That
//! asymmetry is the classic source of namespace bugs, so it is
//! explicit in the parser rather than assumed.
//!
//! ## Feature flags
//!
//! - `std` *(default)* — standard library integration, including
//! `std::error::Error`.
//! - `xpath` *(default)* — the `XPath` engine. Turn it off if you only
//! need to parse.
extern crate alloc;
extern crate std;
/// The README's examples, compiled as doctests.
///
/// `include_str!` rather than a copy: a snapshot of the README in a
/// test file drifts from the README the moment either is edited, and a
/// check that silently stops checking is worse than no check. This way
/// every ```rust block in the README is compiled and run by
/// `cargo test`, and a broken example fails the build.
/// Gated on the features the README demonstrates: its examples use
/// XPath, so under `--no-default-features` they would fail to compile
/// for a reason that says nothing about the crate.
;
pub use ;
pub use parse;
pub use ;
pub use ;