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