1use serde::Serialize;
11use std::fmt::{Display, Formatter, Write};
12use std::io::prelude::*;
13use std::io::Cursor;
14use std::str::FromStr;
15
16use crate::reader::{EventReader, Namespace, OwnedAttribute, OwnedName, XmlEvent};
17
18#[derive(Debug, Clone)]
20pub struct XmlDocument {
21 pub data: Vec<XmlData>,
23}
24
25impl Display for XmlDocument {
26 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
27 for item in self.data.iter() {
28 item.fmt(f)?;
29 }
30 Ok(())
31 }
32}
33
34#[derive(Debug, Clone, Serialize)]
45pub struct XmlData {
46 pub name: String,
48 pub attributes: Vec<(String, String)>,
50 pub data: Option<String>,
52 pub children: Vec<XmlData>,
54}
55
56impl XmlData {
57 fn format(self: &XmlData, f: &mut Formatter, _depth: usize) -> std::fmt::Result {
59 write!(f, "<{}", self.name)?;
60
61 for (key, val) in self.attributes.iter() {
62 write!(f, r#" {key}="{val}""#)?;
63 }
64
65 f.write_char('>')?;
66
67 if let Some(ref data) = self.data {
68 write!(f, "{data}")?
69 }
70
71 for child in self.children.iter() {
72 child.format(f, _depth + 1)?;
73 }
74
75 write!(f, "</{}>", self.name)
76 }
77}
78
79impl Display for XmlData {
80 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
81 self.format(f, 0)
82 }
83}
84
85fn map_owned_attributes(attrs: Vec<OwnedAttribute>) -> Vec<(String, String)> {
87 attrs
88 .into_iter()
89 .map(|attr| {
90 let fmt_name = match attr.name.prefix {
91 Some(prefix) if !attr.name.local_name.is_empty() => {
92 format!("{}:{}", prefix, attr.name.local_name)
93 }
94 Some(prefix) => prefix,
95 None => attr.name.local_name,
96 };
97 (fmt_name, attr.value)
98 })
99 .collect()
100}
101
102fn parse(
103 mut data: Vec<XmlEvent>,
104 current: Option<XmlData>,
105 mut current_vec: Vec<XmlData>,
106 trim: bool,
107 current_namespace: Namespace,
108) -> Result<(Vec<XmlData>, Vec<XmlEvent>), String> {
109 if let Some(elmt) = data.pop() {
110 match elmt {
111 XmlEvent::StartElement {
112 name,
113 attributes,
114 namespace,
115 } => {
116 let fmt_name = match name.prefix {
117 Some(prefix) if !name.local_name.is_empty() => {
118 format!("{}:{}", prefix, name.local_name)
119 }
120 Some(prefix) => prefix,
121 None => name.local_name,
122 };
123
124 let attributes = if namespace == current_namespace {
125 attributes
126 } else {
127 let mut attributes = attributes;
128 let n = namespace.clone();
129 let ns = n
130 .into_iter()
131 .filter(|(_k, v)| {
132 (!v.is_empty())
133 && (v != "http://www.w3.org/2000/xmlns/")
134 && (v != "http://www.w3.org/XML/1998/namespace")
135 })
136 .map(|(k, v)| OwnedAttribute {
137 name: OwnedName {
138 local_name: k.to_string(),
139 namespace: if v.is_empty() {
140 None
141 } else {
142 Some(v.to_string())
143 },
144 prefix: Some("xmlns".to_string()),
145 },
146 value: v.to_string(),
147 });
148 attributes.extend(ns);
149 attributes
150 };
151
152 let inner = XmlData {
153 name: fmt_name,
154 attributes: map_owned_attributes(attributes),
155 data: None,
156 children: Vec::new(),
157 };
158
159 let (inner, rest) = parse(data, Some(inner), Vec::new(), trim, namespace.clone())?;
160
161 if let Some(mut crnt) = current {
162 crnt.children.extend(inner);
163 parse(rest, Some(crnt), current_vec, trim, namespace)
164 } else {
165 current_vec.extend(inner);
166 parse(rest, None, current_vec, trim, namespace)
167 }
168 }
169 XmlEvent::Characters(chr) => {
170 let chr = if trim { chr.trim().to_string() } else { chr };
171 if let Some(mut crnt) = current {
172 crnt.data = Some(chr);
173 parse(data, Some(crnt), current_vec, trim, current_namespace)
174 } else {
175 Err("Invalid form of XML doc".to_string())
176 }
177 }
178 XmlEvent::EndElement { name } => {
179 let fmt_name = match &name.prefix {
180 Some(prefix) if !name.local_name.is_empty() => {
181 format!("{}:{}", prefix, name.local_name)
182 }
183 Some(prefix) => prefix.clone(),
184 None => name.local_name.clone(),
185 };
186 if let Some(crnt) = current {
187 if crnt.name == fmt_name {
188 current_vec.push(crnt);
189 Ok((current_vec, data))
190 } else {
191 Err(format!(
192 "Invalid end tag: expected {}, got {}",
193 crnt.name, name.local_name
194 ))
195 }
196 } else {
197 Err(format!("Invalid end tag: {}", name.local_name))
198 }
199 }
200 _ => parse(data, current, current_vec, trim, current_namespace),
201 }
202 } else if let Some(_current) = current {
203 Err("Invalid end tag".to_string())
204 } else {
205 Ok((current_vec, Vec::new()))
206 }
207}
208
209impl XmlDocument {
210 pub fn from_reader<R>(source: R, trim: bool) -> Result<Self, ParseXmlError>
211 where
212 R: Read,
213 {
214 let parser = EventReader::new(source);
215 let mut events: Vec<XmlEvent> = parser.into_iter().map(|x| x.unwrap()).collect();
216 events.reverse();
217
218 parse(events, None, Vec::new(), trim, Namespace::empty())
219 .map(|(data, _)| XmlDocument { data })
220 .map_err(ParseXmlError)
221 }
222}
223
224#[derive(Debug, Clone, PartialEq)]
226pub struct ParseXmlError(String);
227
228impl Display for ParseXmlError {
229 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
230 write!(f, "Coult not parse string to XML: {}", self.0)
231 }
232}
233
234impl FromStr for XmlDocument {
236 type Err = ParseXmlError;
237
238 fn from_str(s: &str) -> Result<XmlDocument, ParseXmlError> {
239 XmlDocument::from_reader(Cursor::new(s.to_string().into_bytes()), true)
240 }
241}