xee_name/
namespaces.rs

1use ahash::{HashMap, HashMapExt};
2
3/// The XPath FN namespace URI
4pub const FN_NAMESPACE: &str = "http://www.w3.org/2005/xpath-functions";
5/// The XML Schema XS namespace URI
6pub const XS_NAMESPACE: &str = "http://www.w3.org/2001/XMLSchema";
7const XML_NAMESPACE: &str = "http://www.w3.org/XML/1998/namespace";
8
9const STATIC_NAMESPACES: [(&str, &str); 7] = [
10    ("xs", XS_NAMESPACE),
11    ("fn", FN_NAMESPACE),
12    ("math", "http://www.w3.org/2005/xpath-functions/math"),
13    ("map", "http://www.w3.org/2005/xpath-functions/map"),
14    ("array", "http://www.w3.org/2005/xpath-functions/array"),
15    ("err", "http://www.w3.org/2005/xqt-errors"),
16    ("output", "http://www.w3.org/2010/xslt-xquery-serialization"),
17];
18
19/// Declared namespaces.
20#[derive(Debug, Clone)]
21pub struct Namespaces {
22    namespaces: HashMap<String, String>,
23    /// The default namespace for elements in XPath expressions.
24    pub default_element_namespace: String,
25    /// The default namespace for functions in XPath expressions.
26    pub default_function_namespace: String,
27}
28
29impl Namespaces {
30    /// The XPath FN namespace URI
31    pub const FN_NAMESPACE: &'static str = FN_NAMESPACE;
32
33    /// Create a new namespace struct.
34    pub fn new(
35        namespaces: HashMap<String, String>,
36        default_element_namespace: String,
37        default_function_namespace: String,
38    ) -> Self {
39        Self {
40            namespaces,
41            default_element_namespace,
42            default_function_namespace,
43        }
44    }
45
46    /// The default known namespaces for XPath.
47    pub fn default_namespaces() -> HashMap<String, String> {
48        let mut namespaces = HashMap::new();
49        namespaces.insert("xml".to_string(), XML_NAMESPACE.to_string());
50        for (prefix, uri) in STATIC_NAMESPACES.into_iter() {
51            namespaces.insert(prefix.to_string(), uri.to_string());
52        }
53        namespaces
54    }
55
56    /// Add a list of namespace declarations (prefix, uri) to the namespace
57    /// store.
58    pub fn add(&mut self, namespace_pairs: &[(&str, &str)]) {
59        for (prefix, namespace) in namespace_pairs {
60            if prefix.is_empty() {
61                self.default_element_namespace = namespace.to_string();
62            } else {
63                self.namespaces
64                    .insert(prefix.to_string(), namespace.to_string());
65            }
66        }
67    }
68
69    /// Get the namespace URI for a given prefix.
70    #[inline]
71    pub fn by_prefix(&self, prefix: &str) -> Option<&str> {
72        self.namespaces.get(prefix).map(String::as_str)
73    }
74
75    /// Get the default element namespace.
76    #[inline]
77    pub fn default_element_namespace(&self) -> &str {
78        self.default_element_namespace.as_str()
79    }
80}
81
82impl Default for Namespaces {
83    fn default() -> Self {
84        Self::new(
85            Self::default_namespaces(),
86            "".to_string(),
87            FN_NAMESPACE.to_string(),
88        )
89    }
90}
91
92/// A trait for looking up namespace URIs by prefix.
93pub trait NamespaceLookup {
94    /// Get the namespace URI for a given prefix.
95    fn by_prefix(&self, prefix: &str) -> Option<&str>;
96}
97
98impl NamespaceLookup for Namespaces {
99    fn by_prefix(&self, prefix: &str) -> Option<&str> {
100        self.namespaces.get(prefix).map(String::as_str)
101    }
102}
103
104impl<T: NamespaceLookup> NamespaceLookup for &T {
105    fn by_prefix(&self, prefix: &str) -> Option<&str> {
106        (**self).by_prefix(prefix)
107    }
108}