1use crate::prefixes::{Prefix, Prefixes};
6use crate::{Element, Error};
7use rxml::RawEvent;
8use std::collections::BTreeMap;
9
10pub struct TreeBuilder {
12 next_tag: Option<(Prefix, String, Prefixes, BTreeMap<String, String>)>,
13 stack: Vec<Element>,
15 prefixes_stack: Vec<Prefixes>,
17 pub root: Option<Element>,
19}
20
21impl Default for TreeBuilder {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27impl TreeBuilder {
28 #[must_use]
30 pub fn new() -> Self {
31 TreeBuilder {
32 next_tag: None,
33 stack: vec![],
34 prefixes_stack: vec![],
35 root: None,
36 }
37 }
38
39 #[must_use]
44 pub fn with_prefixes_stack(mut self, prefixes_stack: Vec<Prefixes>) -> Self {
45 self.prefixes_stack = prefixes_stack;
46 self
47 }
48
49 #[must_use]
51 pub fn depth(&self) -> usize {
52 self.stack.len()
53 }
54
55 #[must_use]
57 pub fn top(&mut self) -> Option<&Element> {
58 self.stack.last()
59 }
60
61 fn pop(&mut self) -> Option<Element> {
63 self.prefixes_stack.pop();
64 self.stack.pop()
65 }
66
67 pub fn unshift_child(&mut self) -> Option<Element> {
69 let depth = self.stack.len();
70 if depth > 0 {
71 self.stack[depth - 1].unshift_child()
72 } else {
73 None
74 }
75 }
76
77 #[must_use]
79 fn lookup_prefix(&self, prefix: &Option<String>) -> Option<&str> {
80 for nss in self.prefixes_stack.iter().rev() {
81 if let Some(ns) = nss.get(prefix) {
82 return Some(ns);
83 }
84 }
85
86 None
87 }
88
89 fn process_end_tag(&mut self) {
90 if let Some(el) = self.pop() {
91 if self.depth() > 0 {
92 let top = self.stack.len() - 1;
93 self.stack[top].append_child(el);
94 } else {
95 self.root = Some(el);
96 }
97 }
98 }
99
100 fn process_text(&mut self, text: String) {
101 if self.depth() > 0 {
102 let top = self.stack.len() - 1;
103 self.stack[top].append_text(text);
104 }
105 }
106
107 pub fn process_event(&mut self, event: RawEvent) -> Result<(), Error> {
109 match event {
110 RawEvent::XmlDeclaration(_, _) => {}
111
112 RawEvent::ElementHeadOpen(_, (prefix, name)) => {
113 self.next_tag = Some((
114 prefix.map(|prefix| prefix.as_str().to_owned()),
115 name.as_str().to_owned(),
116 Prefixes::default(),
117 BTreeMap::new(),
118 ));
119 }
120
121 RawEvent::Attribute(_, (prefix, name), value) => {
122 if let Some((_, _, ref mut prefixes, ref mut attrs)) = self.next_tag.as_mut() {
123 match (prefix, name) {
124 (None, xmlns) if xmlns == "xmlns" => prefixes.insert(None, value),
125 (Some(xmlns), prefix) if xmlns.as_str() == "xmlns" => {
126 prefixes.insert(Some(prefix.as_str().to_owned()), value);
127 }
128 (Some(prefix), name) => {
129 attrs.insert(format!("{prefix}:{name}"), value.as_str().to_owned());
130 }
131 (None, name) => {
132 attrs.insert(name.as_str().to_owned(), value.as_str().to_owned());
133 }
134 }
135 }
136 }
137
138 RawEvent::ElementHeadClose(_) => {
139 if let Some((prefix, name, prefixes, attrs)) = self.next_tag.take() {
140 self.prefixes_stack.push(prefixes.clone());
141
142 let namespace = self
143 .lookup_prefix(&prefix.map(|prefix| prefix.as_str().to_owned()))
144 .ok_or(Error::MissingNamespace)?
145 .to_owned();
146 let el =
147 Element::new(name.as_str().to_owned(), namespace, prefixes, attrs, vec![]);
148 self.stack.push(el);
149 }
150 }
151
152 RawEvent::ElementFoot(_) => self.process_end_tag(),
153
154 RawEvent::Text(_, text) => self.process_text(text.as_str().to_owned()),
155 }
156
157 Ok(())
158 }
159}