1use ahash::{HashMap, HashMapExt};
2
3pub const FN_NAMESPACE: &str = "http://www.w3.org/2005/xpath-functions";
5pub 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#[derive(Debug, Clone)]
21pub struct Namespaces {
22 namespaces: HashMap<String, String>,
23 pub default_element_namespace: String,
25 pub default_function_namespace: String,
27}
28
29impl Namespaces {
30 pub const FN_NAMESPACE: &'static str = FN_NAMESPACE;
32
33 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 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 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 #[inline]
71 pub fn by_prefix(&self, prefix: &str) -> Option<&str> {
72 self.namespaces.get(prefix).map(String::as_str)
73 }
74
75 #[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
92pub trait NamespaceLookup {
94 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}