css_to_xpath/lib.rs
1#![doc = include_str!("../README.md")]
2#![forbid(unsafe_code)]
3#![warn(missing_docs)]
4
5mod parser;
6mod translate;
7
8pub use parser::MAX_NESTING_DEPTH;
9pub use translate::{
10 Error, MAX_NTH_OF_BYTES, MAX_NTH_OF_DEPTH, Mode, ParseErrorKind, ParseModeError, Translator,
11};
12
13/// A `prefix` that searches the context node and its whole subtree:
14/// `"a"` becomes `descendant-or-self::a`.
15pub const DESCENDANT_OR_SELF: &str = "descendant-or-self::";
16
17/// A `prefix` that searches the whole document, wherever the expression
18/// is evaluated from: `"a"` becomes `//a`.
19pub const WHOLE_DOCUMENT: &str = "//";
20
21/// Translate a CSS selector to an XPath 1.0 expression.
22///
23/// # Arguments
24///
25/// * `css` — A CSS selector string.
26/// * `prefix` — An XPath path prefix prepended verbatim to each
27/// selector-group branch, so it must end in something a node test can
28/// follow: an axis ([`DESCENDANT_OR_SELF`]) or a step separator
29/// ([`WHOLE_DOCUMENT`]). Pass `""` for a bare relative expression.
30/// Nothing validates it — `"/html/body "` yields `/html/body div`,
31/// which XPath reads as a division, not a path. A selector group
32/// anchored on `:scope` ignores `prefix` and anchors on `self::`
33/// instead.
34/// * `mode` — The translator flavour: [`Mode::Generic`], [`Mode::Html`], or
35/// [`Mode::Xhtml`].
36///
37/// # Errors
38///
39/// Returns an [`Error`] when the selector is syntactically invalid or uses
40/// an unsupported construct.
41pub fn css_to_xpath(css: &str, prefix: &str, mode: Mode) -> Result<String, Error> {
42 Translator::new(mode).css_to_xpath(css, prefix)
43}