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