1use crate::element_builder::{BuilderError, ElementBuilder};
11use crate::parser::Parser;
12use crate::{escape, AttrMap, Xml};
13
14use std::collections::HashMap;
15use std::fmt;
16use std::iter::IntoIterator;
17use std::slice;
18use std::str::FromStr;
19
20#[derive(Clone, PartialEq, Debug)]
21pub struct Element {
23 pub name: String,
25 pub ns: Option<String>,
27 pub attributes: AttrMap<(String, Option<String>), String>,
29 pub children: Vec<Xml>,
31 pub(crate) prefixes: HashMap<String, String>,
33 pub(crate) default_ns: Option<String>,
35}
36
37fn fmt_elem(
38 elem: &Element,
39 parent: Option<&Element>,
40 all_prefixes: &HashMap<String, String>,
41 f: &mut fmt::Formatter,
42) -> fmt::Result {
43 let mut all_prefixes = all_prefixes.clone();
44 all_prefixes.extend(elem.prefixes.clone().into_iter());
45
46 if elem.ns != elem.default_ns {
48 let prefix = all_prefixes
49 .get(elem.ns.as_ref().map_or("", |x| &x[..]))
50 .expect("No namespace prefix bound");
51 write!(f, "<{}:{}", *prefix, elem.name)?;
52 } else {
53 write!(f, "<{}", elem.name)?;
54 }
55
56 if !elem
58 .attributes
59 .iter()
60 .any(|(&(ref name, _), _)| name == "xmlns")
61 {
62 match (parent, &elem.default_ns) {
63 (None, &Some(ref ns)) => write!(f, " xmlns='{}'", *ns)?,
65 (Some(parent), ns) if parent.default_ns != *ns => {
67 write!(f, " xmlns='{}'", ns.as_ref().map_or("", |x| &x[..]))?
68 }
69 _ => (),
70 }
71 }
72
73 for (&(ref name, ref ns), value) in &elem.attributes {
74 match *ns {
75 Some(ref ns) => {
76 let prefix = all_prefixes.get(ns).expect("No namespace prefix bound");
77 write!(f, " {}:{}='{}'", *prefix, name, escape(value))?
78 }
79 None => write!(f, " {}='{}'", name, escape(value))?,
80 }
81 }
82
83 if elem.children.is_empty() {
84 write!(f, "/>")?;
85 } else {
86 write!(f, ">")?;
87 for child in &elem.children {
88 match *child {
89 Xml::ElementNode(ref child) => fmt_elem(child, Some(elem), &all_prefixes, f)?,
90 ref o => fmt::Display::fmt(o, f)?,
91 }
92 }
93 if elem.ns != elem.default_ns {
94 let prefix = all_prefixes
95 .get(elem.ns.as_ref().unwrap())
96 .expect("No namespace prefix bound");
97 write!(f, "</{}:{}>", *prefix, elem.name)?;
98 } else {
99 write!(f, "</{}>", elem.name)?;
100 }
101 }
102
103 Ok(())
104}
105
106impl fmt::Display for Element {
107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108 fmt_elem(self, None, &HashMap::new(), f)
109 }
110}
111
112pub struct ChildElements<'a, 'b> {
114 elems: slice::Iter<'a, Xml>,
115 name: &'b str,
116 ns: Option<&'b str>,
117}
118
119impl<'a, 'b> Iterator for ChildElements<'a, 'b> {
120 type Item = &'a Element;
121
122 fn next(&mut self) -> Option<&'a Element> {
123 let (name, ns) = (self.name, self.ns);
124 self.elems.by_ref().find_map(|child| {
125 if let Xml::ElementNode(ref elem) = *child {
126 if name == elem.name && ns == elem.ns.as_ref().map(|x| &x[..]) {
127 return Some(elem);
128 }
129 }
130 None
131 })
132 }
133}
134
135impl Element {
136 pub fn new<A>(name: String, ns: Option<String>, attrs: A) -> Element
139 where
140 A: IntoIterator<Item = (String, Option<String>, String)>,
141 {
142 let mut prefixes = HashMap::with_capacity(2);
143 prefixes.insert(
144 "http://www.w3.org/XML/1998/namespace".to_owned(),
145 "xml".to_owned(),
146 );
147 prefixes.insert(
148 "http://www.w3.org/2000/xmlns/".to_owned(),
149 "xmlns".to_owned(),
150 );
151
152 let attributes: AttrMap<_, _> = attrs
153 .into_iter()
154 .map(|(name, ns, value)| ((name, ns), value))
155 .collect();
156
157 Element {
158 name,
159 ns: ns.clone(),
160 default_ns: ns,
161 prefixes,
162 attributes,
163 children: Vec::new(),
164 }
165 }
166
167 pub fn content_str(&self) -> String {
169 let mut res = String::new();
170 for child in &self.children {
171 match *child {
172 Xml::ElementNode(ref elem) => res.push_str(&elem.content_str()),
173 Xml::CharacterNode(ref data) | Xml::CDATANode(ref data) => res.push_str(data),
174 _ => (),
175 }
176 }
177 res
178 }
179
180 pub fn get_attribute<'a>(&'a self, name: &str, ns: Option<&str>) -> Option<&'a str> {
183 self.attributes
184 .get(&(name.to_owned(), ns.map(|x| x.to_owned())))
185 .map(|x| &x[..])
186 }
187
188 pub fn set_attribute(
191 &mut self,
192 name: String,
193 ns: Option<String>,
194 value: String,
195 ) -> Option<String> {
196 self.attributes.insert((name, ns), value)
197 }
198
199 pub fn remove_attribute(&mut self, name: &str, ns: Option<&str>) -> Option<String> {
202 self.attributes
203 .remove(&(name.to_owned(), ns.map(|x| x.to_owned())))
204 }
205
206 pub fn get_child<'a>(&'a self, name: &str, ns: Option<&str>) -> Option<&'a Element> {
209 self.get_children(name, ns).next()
210 }
211
212 pub fn get_children<'a, 'b>(
215 &'a self,
216 name: &'b str,
217 ns: Option<&'b str>,
218 ) -> ChildElements<'a, 'b> {
219 ChildElements {
220 elems: self.children.iter(),
221 name,
222 ns,
223 }
224 }
225
226 pub fn tag(&mut self, child: Element) -> &mut Element {
228 self.children.push(Xml::ElementNode(child));
229 match self.children.last_mut() {
230 Some(Xml::ElementNode(ref mut elem)) => elem,
231 _ => unreachable!("Could not get reference to just added element!"),
232 }
233 }
234
235 pub fn tag_stay(&mut self, child: Element) -> &mut Element {
237 self.children.push(Xml::ElementNode(child));
238 self
239 }
240
241 pub fn text(&mut self, text: String) -> &mut Element {
243 self.children.push(Xml::CharacterNode(text));
244 self
245 }
246
247 pub fn cdata(&mut self, text: String) -> &mut Element {
249 self.children.push(Xml::CDATANode(text));
250 self
251 }
252
253 pub fn comment(&mut self, text: String) -> &mut Element {
255 self.children.push(Xml::CommentNode(text));
256 self
257 }
258
259 pub fn pi(&mut self, text: String) -> &mut Element {
261 self.children.push(Xml::PINode(text));
262 self
263 }
264}
265
266impl FromStr for Element {
267 type Err = BuilderError;
268 #[inline]
269 fn from_str(data: &str) -> Result<Element, BuilderError> {
270 let mut p = Parser::new();
271 let mut e = ElementBuilder::new();
272
273 p.feed_str(data);
274 p.find_map(|x| e.handle_event(x))
275 .unwrap_or(Err(BuilderError::NoElement))
276 }
277}
278
279#[cfg(test)]
280mod tests {
281 use super::Element;
282
283 #[test]
284 fn test_get_children() {
285 let elem: Element = "<a><b/><c/><b/></a>".parse().unwrap();
286 assert_eq!(
287 elem.get_children("b", None).collect::<Vec<_>>(),
288 vec![
289 &Element::new("b".to_owned(), None, vec![]),
290 &Element::new("b".to_owned(), None, vec![])
291 ],
292 );
293 }
294
295 #[test]
296 fn test_get_child() {
297 let elem: Element = "<a><b/><c/><b/></a>".parse().unwrap();
298 assert_eq!(
299 elem.get_child("b", None),
300 Some(&Element::new("b".to_owned(), None, vec![])),
301 );
302 }
303
304 #[test]
305 #[cfg(feature = "ordered_attrs")]
306 fn test_attribute_order_new() {
307 let input_attributes = vec![
308 ("href".to_owned(), None, "/".to_owned()),
309 ("title".to_owned(), None, "Home".to_owned()),
310 ("target".to_owned(), None, "_blank".to_owned()),
311 ];
312
313 for _ in 0..5 {
315 let elem = Element::new("a".to_owned(), None, input_attributes.clone());
316 for (expected, actual) in input_attributes.iter().zip(elem.attributes) {
317 assert_eq!(expected.0, (actual.0).0);
318 assert_eq!(expected.1, (actual.0).1);
319 assert_eq!(expected.2, actual.1);
320 }
321 }
322 }
323
324 #[test]
325 #[cfg(feature = "ordered_attrs")]
326 fn test_attribute_order_added() {
327 let input_attributes = vec![
328 ("href".to_owned(), None, "/".to_owned()),
329 ("title".to_owned(), None, "Home".to_owned()),
330 ("target".to_owned(), None, "_blank".to_owned()),
331 ];
332
333 for _ in 0..5 {
335 let mut elem = Element::new("a".to_owned(), None, vec![]);
336 for attr in &input_attributes {
337 elem.set_attribute(attr.0.clone(), attr.1.clone(), attr.2.clone());
338 }
339 for (expected, actual) in input_attributes.iter().zip(elem.attributes) {
340 assert_eq!(expected.0, (actual.0).0);
341 assert_eq!(expected.1, (actual.0).1);
342 assert_eq!(expected.2, actual.1);
343 }
344 }
345 }
346}