1use crate::element_builder::{BuilderError, ElementBuilder};
11use crate::parser::Parser;
12use crate::{escape, 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: HashMap<(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
125 .by_ref()
126 .filter_map(|child| {
127 if let Xml::ElementNode(ref elem) = *child {
128 if name == elem.name && ns == elem.ns.as_ref().map(|x| &x[..]) {
129 return Some(elem);
130 }
131 }
132 None
133 })
134 .next()
135 }
136}
137
138impl Element {
139 pub fn new<A>(name: String, ns: Option<String>, attrs: A) -> Element
142 where
143 A: IntoIterator<Item = (String, Option<String>, String)>,
144 {
145 let mut prefixes = HashMap::with_capacity(2);
146 prefixes.insert(
147 "http://www.w3.org/XML/1998/namespace".to_owned(),
148 "xml".to_owned(),
149 );
150 prefixes.insert(
151 "http://www.w3.org/2000/xmlns/".to_owned(),
152 "xmlns".to_owned(),
153 );
154
155 let attributes: HashMap<_, _> = attrs
156 .into_iter()
157 .map(|(name, ns, value)| ((name, ns), value))
158 .collect();
159
160 Element {
161 name,
162 ns: ns.clone(),
163 default_ns: ns,
164 prefixes,
165 attributes,
166 children: Vec::new(),
167 }
168 }
169
170 pub fn content_str(&self) -> String {
172 let mut res = String::new();
173 for child in &self.children {
174 match *child {
175 Xml::ElementNode(ref elem) => res.push_str(&elem.content_str()),
176 Xml::CharacterNode(ref data) | Xml::CDATANode(ref data) => res.push_str(&data),
177 _ => (),
178 }
179 }
180 res
181 }
182
183 pub fn get_attribute<'a>(&'a self, name: &str, ns: Option<&str>) -> Option<&'a str> {
186 self.attributes
187 .get(&(name.to_owned(), ns.map(|x| x.to_owned())))
188 .map(|x| &x[..])
189 }
190
191 pub fn set_attribute(
194 &mut self,
195 name: String,
196 ns: Option<String>,
197 value: String,
198 ) -> Option<String> {
199 self.attributes.insert((name, ns), value)
200 }
201
202 pub fn remove_attribute(&mut self, name: &str, ns: Option<&str>) -> Option<String> {
205 self.attributes
206 .remove(&(name.to_owned(), ns.map(|x| x.to_owned())))
207 }
208
209 pub fn get_child<'a>(&'a self, name: &str, ns: Option<&str>) -> Option<&'a Element> {
212 self.get_children(name, ns).next()
213 }
214
215 pub fn get_children<'a, 'b>(
218 &'a self,
219 name: &'b str,
220 ns: Option<&'b str>,
221 ) -> ChildElements<'a, 'b> {
222 ChildElements {
223 elems: self.children.iter(),
224 name,
225 ns,
226 }
227 }
228
229 pub fn tag(&mut self, child: Element) -> &mut Element {
231 self.children.push(Xml::ElementNode(child));
232 let error = "Internal error: Could not get reference to new element!";
233 match *self.children.last_mut().expect(error) {
234 Xml::ElementNode(ref mut elem) => elem,
235 _ => panic!(error),
236 }
237 }
238
239 pub fn tag_stay(&mut self, child: Element) -> &mut Element {
241 self.children.push(Xml::ElementNode(child));
242 self
243 }
244
245 pub fn text(&mut self, text: String) -> &mut Element {
247 self.children.push(Xml::CharacterNode(text));
248 self
249 }
250
251 pub fn cdata(&mut self, text: String) -> &mut Element {
253 self.children.push(Xml::CDATANode(text));
254 self
255 }
256
257 pub fn comment(&mut self, text: String) -> &mut Element {
259 self.children.push(Xml::CommentNode(text));
260 self
261 }
262
263 pub fn pi(&mut self, text: String) -> &mut Element {
265 self.children.push(Xml::PINode(text));
266 self
267 }
268}
269
270impl FromStr for Element {
271 type Err = BuilderError;
272 #[inline]
273 fn from_str(data: &str) -> Result<Element, BuilderError> {
274 let mut p = Parser::new();
275 let mut e = ElementBuilder::new();
276
277 p.feed_str(data);
278 p.filter_map(|x| e.handle_event(x))
279 .next()
280 .unwrap_or(Err(BuilderError::NoElement))
281 }
282}
283
284#[cfg(test)]
285mod tests {
286 use super::Element;
287
288 #[test]
289 fn test_get_children() {
290 let elem: Element = "<a><b/><c/><b/></a>".parse().unwrap();
291 assert_eq!(
292 elem.get_children("b", None).collect::<Vec<_>>(),
293 vec![
294 &Element::new("b".to_owned(), None, vec![]),
295 &Element::new("b".to_owned(), None, vec![])
296 ],
297 );
298 }
299
300 #[test]
301 fn test_get_child() {
302 let elem: Element = "<a><b/><c/><b/></a>".parse().unwrap();
303 assert_eq!(
304 elem.get_child("b", None),
305 Some(&Element::new("b".to_owned(), None, vec![])),
306 );
307 }
308}