#![warn(missing_docs)]
#![warn(rustdoc::missing_crate_level_docs)]
#![allow(clippy::collapsible_if)]
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::collapsible_match)]
#![allow(clippy::large_enum_variant)]
pub mod document;
pub mod error;
pub mod event;
pub mod generator;
pub mod namespace;
pub mod node;
pub mod parser;
pub mod position;
pub mod profile;
pub mod schema;
pub mod serialize;
pub mod transform;
pub mod xpath;
pub use error::{Error, ErrorLevel, ErrorLocation, Result, StructuredError, ValidationErrorType};
pub use document::{DocumentBuilder, XmlDocument};
pub use node::{NodeId, NodeType, XmlNode, XmlRoNode};
pub use namespace::{Namespace, NamespaceResolver};
pub use compact_str::CompactString;
pub use parser::{
ParserOptions, parse, parse_from_bufread, parse_schema_locations, parse_with_options,
};
pub use position::PositionTrackingReader;
pub use xpath::context::{XmlContext, XmlSafeContext};
pub fn evaluate<T: AsRef<str>>(
document: &XmlDocument,
xpath_expr: T,
) -> Result<xpath::XPathResult> {
xpath::evaluate(document, xpath_expr.as_ref())
}
pub fn create_context(document: &XmlDocument) -> Result<XmlContext> {
xpath::create_context(document)
}
pub fn create_safe_context(document: &XmlDocument) -> Result<XmlSafeContext> {
xpath::create_safe_context(document)
}
pub fn find_nodes_by_xpath(
ctx: &XmlContext,
xpath_expr: &str,
node: &XmlNode,
) -> Result<Vec<XmlNode>> {
xpath::find_nodes_by_xpath(ctx, xpath_expr, node)
}
pub fn find_readonly_nodes_by_xpath(
ctx: &XmlContext,
xpath_expr: &str,
node: &XmlRoNode,
) -> Result<Vec<XmlRoNode>> {
xpath::find_readonly_nodes_by_xpath(ctx, xpath_expr, node)
}
pub fn find_safe_readonly_nodes_by_xpath(
ctx: &XmlSafeContext,
xpath_expr: &str,
node: &XmlRoNode,
) -> Result<Vec<XmlRoNode>> {
xpath::find_safe_readonly_nodes_by_xpath(ctx, xpath_expr, node)
}
pub fn find_readonly_nodes_in_elements(
ctx: &XmlContext,
node: &XmlRoNode,
elements_to_match: &[&str],
) -> Result<Vec<XmlRoNode>> {
xpath::find_readonly_nodes_in_elements(ctx, node, elements_to_match)
}
pub fn collect_text_values(xpath_value: &xpath::XPathResult) -> Vec<String> {
xpath::collect_text_values(xpath_value)
}
pub fn collect_text_value(xpath_value: &xpath::XPathResult) -> String {
xpath::collect_text_value(xpath_value)
}
pub fn get_root_node(document: &XmlDocument) -> Result<XmlNode> {
document.get_root_element()
}
pub fn get_root_readonly_node(document: &XmlDocument) -> Result<XmlRoNode> {
document.get_root_element_ro()
}
pub fn get_node_tag(node: &XmlNode) -> String {
node.qname()
}
pub fn get_readonly_node_tag(node: &XmlRoNode) -> String {
node.qname()
}
pub fn get_node_prefix(node: &XmlNode) -> String {
node.get_prefix().unwrap_or_default()
}
pub fn get_readonly_node_prefix(node: &XmlRoNode) -> String {
node.get_prefix().unwrap_or_default()
}
pub fn node_to_xml_string(document: &XmlDocument, node: &mut XmlNode) -> Result<String> {
serialize::node_to_xml_string(document, node)
}
pub fn readonly_node_to_xml_string(document: &XmlDocument, node: &XmlRoNode) -> Result<String> {
serialize::readonly_node_to_xml_string(document, node)
}
pub fn create_xml_schema_validation_context(
schema_location: String,
) -> Result<schema::XmlSchemaValidationContext> {
schema::create_xml_schema_validation_context(&schema_location)
}
pub fn create_xml_schema_validation_context_from_buffer(
schema: &[u8],
) -> Result<schema::XmlSchemaValidationContext> {
schema::create_xml_schema_validation_context_from_buffer(schema)
}
pub fn validate_document_by_schema(
document: &XmlDocument,
schema_location: String,
) -> Result<Vec<StructuredError>> {
schema::validate_document_by_schema(document, &schema_location)
}
pub fn validate_document_by_schema_context(
document: &XmlDocument,
ctx: &schema::XmlSchemaValidationContext,
) -> Result<Vec<StructuredError>> {
schema::validate_document_by_schema_context(document, ctx)
}
pub fn parse_xsd(content: &[u8]) -> Result<schema::types::CompiledSchema> {
schema::parse_xsd(content)
}
pub fn parse_xsd_with_imports<F: schema::SchemaFetcher>(
content: &[u8],
base_uri: &str,
fetcher: &F,
) -> Result<schema::types::CompiledSchema> {
schema::parse_xsd_with_imports(content, base_uri, fetcher)
}
pub fn parse_xsd_with_imports_multiple<F: schema::SchemaFetcher>(
entries: &[(&str, &[u8])],
fetcher: &F,
) -> Result<schema::types::CompiledSchema> {
schema::parse_xsd_with_imports_multiple(entries, fetcher)
}
#[cfg(feature = "tokio")]
pub async fn parse_xsd_with_imports_multiple_async<F: schema::AsyncSchemaFetcher>(
entries: &[(&str, &[u8])],
fetcher: &F,
) -> Result<schema::types::CompiledSchema> {
schema::parse_xsd_with_imports_multiple_async(entries, fetcher).await
}
#[cfg(feature = "tokio")]
pub async fn parse_xsd_with_imports_async<F: schema::AsyncSchemaFetcher>(
content: &[u8],
base_uri: &str,
fetcher: &F,
) -> Result<schema::types::CompiledSchema> {
schema::parse_xsd_with_imports_async(content, base_uri, fetcher).await
}
#[cfg(feature = "ureq")]
pub fn validate_with_schema_location(document: &XmlDocument) -> Result<Vec<StructuredError>> {
schema::validate_with_schema_location(document)
}
pub fn validate_with_schema_location_and_fetcher<F: schema::SchemaFetcher>(
document: &XmlDocument,
fetcher: &F,
) -> Result<Vec<StructuredError>> {
schema::validate_with_schema_location_and_fetcher(document, fetcher)
}
#[cfg(feature = "ureq")]
pub fn get_schema_from_schema_location(
xml_content: &[u8],
) -> Result<schema::types::CompiledSchema> {
schema::get_schema_from_schema_location(xml_content)
}
pub fn get_schema_from_schema_location_with_fetcher<F: schema::SchemaFetcher>(
xml_content: &[u8],
fetcher: &F,
) -> Result<schema::types::CompiledSchema> {
schema::get_schema_from_schema_location_with_fetcher(xml_content, fetcher)
}
#[cfg(feature = "ureq")]
pub fn streaming_validate_with_schema_location<R: std::io::BufRead>(
reader: R,
) -> Result<Vec<StructuredError>> {
schema::streaming_validate_with_schema_location(reader)
}
pub fn streaming_validate_with_schema_location_and_fetcher<
R: std::io::BufRead,
F: schema::SchemaFetcher + 'static,
>(
reader: R,
fetcher: F,
) -> Result<Vec<StructuredError>> {
schema::streaming_validate_with_schema_location_and_fetcher(reader, fetcher)
}
#[cfg(feature = "tokio")]
pub async fn validate_with_schema_location_async(
document: &XmlDocument,
) -> Result<Vec<StructuredError>> {
schema::validate_with_schema_location_async(document).await
}
#[cfg(feature = "tokio")]
pub async fn validate_with_schema_location_with_async_fetcher<F: schema::AsyncSchemaFetcher>(
document: &XmlDocument,
fetcher: &F,
) -> Result<Vec<StructuredError>> {
schema::validate_with_schema_location_with_async_fetcher(document, fetcher).await
}
#[cfg(feature = "tokio")]
pub async fn get_schema_from_schema_location_async(
xml_content: &[u8],
) -> Result<schema::types::CompiledSchema> {
schema::get_schema_from_schema_location_async(xml_content).await
}
#[cfg(feature = "tokio")]
pub async fn get_schema_from_schema_location_with_async_fetcher<F: schema::AsyncSchemaFetcher>(
xml_content: &[u8],
fetcher: &F,
) -> Result<schema::types::CompiledSchema> {
schema::get_schema_from_schema_location_with_async_fetcher(xml_content, fetcher).await
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_parsing() {
let xml = r#"<root attr="value"><child>text</child></root>"#;
let doc = parse(xml).unwrap();
let root = get_root_node(&doc).unwrap();
assert_eq!(get_node_tag(&root), "root");
}
#[test]
fn test_xpath_evaluation() {
let xml = r#"<root><Building/><Room/><Window/></root>"#;
let doc = parse(xml).unwrap();
let result = evaluate(&doc, "//*[name()='Building']").unwrap();
let nodes = result.into_nodes();
assert_eq!(nodes.len(), 1);
assert_eq!(nodes[0].get_name(), "Building");
}
#[test]
fn test_context_xpath() {
let xml = r#"<root><a>1</a><a>2</a></root>"#;
let doc = parse(xml).unwrap();
let ctx = create_context(&doc).unwrap();
let root = get_root_readonly_node(&doc).unwrap();
let nodes = find_readonly_nodes_by_xpath(&ctx, "//a", &root).unwrap();
assert_eq!(nodes.len(), 2);
}
#[test]
fn test_text_collection() {
let xml = r#"<root><a>one</a><a>two</a></root>"#;
let doc = parse(xml).unwrap();
let result = evaluate(&doc, "/root/a").unwrap();
let texts = collect_text_values(&result);
assert_eq!(texts, vec!["one", "two"]);
}
#[test]
fn test_namespaced_xml() {
let xml = r#"<gml:root xmlns:gml="http://www.opengis.net/gml">
<gml:name>test</gml:name>
</gml:root>"#;
let doc = parse(xml).unwrap();
let result = evaluate(&doc, "/gml:root/gml:name").unwrap();
let nodes = result.into_nodes();
assert_eq!(nodes.len(), 1);
}
#[test]
fn test_serialization() {
let xml = r#"<root><child>text</child></root>"#;
let doc = parse(xml).unwrap();
let mut root = get_root_node(&doc).unwrap();
let serialized = node_to_xml_string(&doc, &mut root).unwrap();
assert!(serialized.contains("<root>"));
assert!(serialized.contains("<child>text</child>"));
}
#[test]
fn test_create_safe_context() {
let xml = r#"<root><a>1</a></root>"#;
let doc = parse(xml).unwrap();
let ctx = create_safe_context(&doc).unwrap();
let root = get_root_readonly_node(&doc).unwrap();
let nodes = find_safe_readonly_nodes_by_xpath(&ctx, "//a", &root).unwrap();
assert_eq!(nodes.len(), 1);
}
#[test]
fn test_find_nodes_by_xpath() {
let xml = r#"<root><a>1</a><b>2</b></root>"#;
let doc = parse(xml).unwrap();
let ctx = create_context(&doc).unwrap();
let root = get_root_node(&doc).unwrap();
let nodes = find_nodes_by_xpath(&ctx, "//a", &root).unwrap();
assert_eq!(nodes.len(), 1);
assert_eq!(nodes[0].get_name(), "a");
}
#[test]
fn test_find_readonly_nodes_in_elements() {
let xml = r#"<root><a>1</a><b>2</b><c>3</c></root>"#;
let doc = parse(xml).unwrap();
let ctx = create_context(&doc).unwrap();
let root = get_root_readonly_node(&doc).unwrap();
let nodes = find_readonly_nodes_in_elements(&ctx, &root, &["a", "c"]).unwrap();
assert_eq!(nodes.len(), 2);
}
#[test]
fn test_collect_text_value_single() {
let xml = r#"<root><a>hello</a></root>"#;
let doc = parse(xml).unwrap();
let result = evaluate(&doc, "/root/a").unwrap();
let text = collect_text_value(&result);
assert_eq!(text, "hello");
}
#[test]
fn test_collect_text_value_empty() {
let xml = r#"<root><a/></root>"#;
let doc = parse(xml).unwrap();
let result = evaluate(&doc, "/root/nonexistent").unwrap();
let text = collect_text_value(&result);
assert!(text.is_empty());
}
#[test]
fn test_get_readonly_node_tag() {
let xml = r#"<ns:root xmlns:ns="http://example.com"/>"#;
let doc = parse(xml).unwrap();
let root = get_root_readonly_node(&doc).unwrap();
assert_eq!(get_readonly_node_tag(&root), "ns:root");
}
#[test]
fn test_get_node_prefix() {
let xml = r#"<ns:root xmlns:ns="http://example.com"/>"#;
let doc = parse(xml).unwrap();
let root = get_root_node(&doc).unwrap();
assert_eq!(get_node_prefix(&root), "ns");
}
#[test]
fn test_get_node_prefix_empty() {
let xml = r#"<root/>"#;
let doc = parse(xml).unwrap();
let root = get_root_node(&doc).unwrap();
assert_eq!(get_node_prefix(&root), "");
}
#[test]
fn test_get_readonly_node_prefix() {
let xml = r#"<ns:root xmlns:ns="http://example.com"/>"#;
let doc = parse(xml).unwrap();
let root = get_root_readonly_node(&doc).unwrap();
assert_eq!(get_readonly_node_prefix(&root), "ns");
}
#[test]
fn test_get_readonly_node_prefix_empty() {
let xml = r#"<root/>"#;
let doc = parse(xml).unwrap();
let root = get_root_readonly_node(&doc).unwrap();
assert_eq!(get_readonly_node_prefix(&root), "");
}
#[test]
fn test_readonly_node_to_xml_string() {
let xml = r#"<root><child>text</child></root>"#;
let doc = parse(xml).unwrap();
let root = get_root_readonly_node(&doc).unwrap();
let serialized = readonly_node_to_xml_string(&doc, &root).unwrap();
assert!(serialized.contains("<root>"));
assert!(serialized.contains("<child>text</child>"));
}
#[test]
fn test_evaluate_with_string_ref() {
let xml = r#"<root><a>1</a></root>"#;
let doc = parse(xml).unwrap();
let xpath_str = String::from("//a");
let result = evaluate(&doc, &xpath_str).unwrap();
let nodes = result.into_nodes();
assert_eq!(nodes.len(), 1);
}
#[test]
fn test_parse_xsd_basic() {
let xsd = br#"<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root" type="xs:string"/>
</xs:schema>"#;
let schema = parse_xsd(xsd).unwrap();
assert!(!schema.elements.is_empty() || !schema.types.is_empty());
}
#[test]
fn test_create_xml_schema_validation_context_from_buffer() {
let xsd = br#"<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root" type="xs:string"/>
</xs:schema>"#;
let ctx = create_xml_schema_validation_context_from_buffer(xsd).unwrap();
let _ = ctx;
}
}