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