xot/
xotdata.rs

1use ahash::{HashMap, HashMapExt};
2use indextree::{Arena, NodeId};
3
4use crate::id::{Name, NameId, NameLookup, NamespaceId, NamespaceLookup, PrefixId, PrefixLookup};
5use crate::xmlvalue::Value;
6
7pub(crate) type XmlArena = Arena<Value>;
8
9/// A node in the XML tree.
10/// This is a lightweight value and can be copied.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub struct Node(NodeId);
13
14impl Node {
15    #[inline]
16    pub(crate) fn new(node_id: NodeId) -> Self {
17        Node(node_id)
18    }
19
20    #[inline]
21    pub(crate) fn get(&self) -> NodeId {
22        self.0
23    }
24}
25
26impl From<NodeId> for Node {
27    #[inline]
28    fn from(node_id: NodeId) -> Self {
29        Node(node_id)
30    }
31}
32
33/// The `Xot` struct manages all XML tree data in your program. It lets you
34/// access and manipulate one or more XML documents and
35/// fragments, as well as unattached trees of nodes.
36///
37/// Xot is implemented in several sections focusing on different aspects
38/// of accessing and manipulating XML data.
39///
40/// The Xot struct documentation is divided into different sections:
41///
42/// * [Read-only access](#read-only-access)
43/// * [Creation](#creation)
44/// * [Manipulation](#manipulation)
45/// * [Names, namespaces and prefixes](#names-namespaces-and-prefixes)
46/// * [Parsing](#parsing)
47/// * [Serialization](#serialization)
48/// * [Value and type access](#value-and-type-access)
49#[derive(Debug, Clone)]
50pub struct Xot {
51    pub(crate) arena: XmlArena,
52    // a mapping of document node, to hashmap of node value to node with that id
53    pub(crate) id_nodes_map: HashMap<NodeId, HashMap<String, NodeId>>,
54    pub(crate) namespace_lookup: NamespaceLookup,
55    pub(crate) prefix_lookup: PrefixLookup,
56    pub(crate) name_lookup: NameLookup,
57    pub(crate) no_namespace_id: NamespaceId,
58    pub(crate) empty_prefix_id: PrefixId,
59    pub(crate) xml_namespace_id: NamespaceId,
60    pub(crate) xml_prefix_id: PrefixId,
61    pub(crate) xml_space_id: NameId,
62    pub(crate) xml_id_id: NameId,
63    pub(crate) text_consolidation: bool,
64}
65
66impl Xot {
67    /// Create a new `Xot` instance.
68    pub fn new() -> Self {
69        let mut namespace_lookup = NamespaceLookup::new();
70        let no_namespace_id = namespace_lookup.get_id_mut("");
71        let mut prefix_lookup = PrefixLookup::new();
72        let empty_prefix_id = prefix_lookup.get_id_mut("");
73        let xml_namespace_id = namespace_lookup.get_id_mut("http://www.w3.org/XML/1998/namespace");
74        let xml_prefix_id = prefix_lookup.get_id_mut("xml");
75        let mut name_lookup = NameLookup::new();
76        let xml_space_id = name_lookup.get_id_mut(&Name::new("space", xml_namespace_id));
77        let xml_id_id = name_lookup.get_id_mut(&Name::new("id", xml_namespace_id));
78        Xot {
79            arena: XmlArena::new(),
80            id_nodes_map: HashMap::new(),
81            namespace_lookup,
82            prefix_lookup,
83            name_lookup,
84            no_namespace_id,
85            empty_prefix_id,
86            xml_namespace_id,
87            xml_prefix_id,
88            xml_space_id,
89            xml_id_id,
90            text_consolidation: true,
91        }
92    }
93
94    #[inline]
95    pub(crate) fn arena(&self) -> &XmlArena {
96        &self.arena
97    }
98
99    #[inline]
100    pub(crate) fn arena_mut(&mut self) -> &mut XmlArena {
101        &mut self.arena
102    }
103}
104
105impl Default for Xot {
106    fn default() -> Self {
107        Self::new()
108    }
109}