1//! Provides an `Element` type, which represents DOM nodes, and a builder to create them with.
2
3use std::io::prelude::*;
4use std::io::Cursor;
5use std::collections::BTreeMap;
6
7use std::fmt;
8
9use error::Error;
10
11use xml::reader::{XmlEvent as ReaderEvent, EventReader};
12use xml::writer::{XmlEvent as WriterEvent, EventWriter, EmitterConfig};
13use xml::name::Name;
14use xml::namespace::NS_NO_PREFIX;
15
16use std::str::FromStr;
17
18use std::slice;
19
20use convert::{IntoElements, IntoAttributeValue, ElementEmitter};
21
22#[derive(Clone, PartialEq, Eq)]
23/// A struct representing a DOM Element.
24pub struct Element {
25 name: String,
26 namespace: Option<String>,
27 attributes: BTreeMap<String, String>,
28 children: Vec<Node>,
29}
30
31
32impl<'a> From<&'a Element> for String {
33 fn from(elem: &'a Element) -> String {
34 let mut out = Vec::new();
35 let config = EmitterConfig::new()
36 .write_document_declaration(false);
37 elem.write_to(&mut EventWriter::new_with_config(&mut out, config)).unwrap();
38 String::from_utf8(out).unwrap()
39 }
40}
41
42impl fmt::Debug for Element {
43 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
44 write!(fmt, "{}", String::from(self))?;
45 Ok(())
46 }
47}
48
49impl FromStr for Element {
50 type Err = Error;
51
52 fn from_str(s: &str) -> Result<Element, Error> {
53 let mut reader = EventReader::new(Cursor::new(s));
54 Element::from_reader(&mut reader)
55 }
56}
57
58/// A node in an element tree.
59#[derive(Clone, Debug, PartialEq, Eq)]
60pub enum Node {
61 /// An `Element`.
62 Element(Element),
63 /// A text node.
64 Text(String),
65}
66
67impl Element {
68 fn new(name: String, namespace: Option<String>, attributes: BTreeMap<String, String>, children: Vec<Node>) -> Element {
69 Element {
70 name: name,
71 namespace: namespace,
72 attributes: attributes,
73 children: children,
74 }
75 }
76
77 /// Return a builder for an `Element` with the given `name`.
78 ///
79 /// # Examples
80 ///
81 /// ```
82 /// use minidom::Element;
83 ///
84 /// let elem = Element::builder("name")
85 /// .ns("namespace")
86 /// .attr("name", "value")
87 /// .append("inner")
88 /// .build();
89 ///
90 /// assert_eq!(elem.name(), "name");
91 /// assert_eq!(elem.ns(), Some("namespace"));
92 /// assert_eq!(elem.attr("name"), Some("value"));
93 /// assert_eq!(elem.attr("inexistent"), None);
94 /// assert_eq!(elem.text(), "inner");
95 /// ```
96 pub fn builder<S: Into<String>>(name: S) -> ElementBuilder {
97 ElementBuilder {
98 root: Element::new(name.into(), None, BTreeMap::new(), Vec::new()),
99 }
100 }
101
102 /// Returns a bare minimum `Element` with this name.
103 ///
104 /// # Examples
105 ///
106 /// ```
107 /// use minidom::Element;
108 ///
109 /// let bare = Element::bare("name");
110 ///
111 /// assert_eq!(bare.name(), "name");
112 /// assert_eq!(bare.ns(), None);
113 /// assert_eq!(bare.attr("name"), None);
114 /// assert_eq!(bare.text(), "");
115 /// ```
116 pub fn bare<S: Into<String>>(name: S) -> Element {
117 Element {
118 name: name.into(),
119 namespace: None,
120 attributes: BTreeMap::new(),
121 children: Vec::new(),
122 }
123 }
124
125 /// Returns a reference to the name of this element.
126 pub fn name(&self) -> &str {
127 &self.name
128 }
129
130 /// Returns a reference to the namespace of this element, if it has one, else `None`.
131 pub fn ns(&self) -> Option<&str> {
132 self.namespace.as_ref()
133 .map(String::as_ref)
134 }
135
136 /// Returns a reference to the value of the given attribute, if it exists, else `None`.
137 pub fn attr(&self, name: &str) -> Option<&str> {
138 if let Some(value) = self.attributes.get(name) {
139 return Some(&value)
140 }
141 None
142 }
143
144 /// Modifies the value of an attribute.
145 pub fn set_attr<S: Into<String>, V: IntoAttributeValue>(&mut self, name: S, val: V) {
146 let name = name.into();
147 let val = val.into_attribute_value();
148
149 if let Some(value) = self.attributes.get_mut(&name) {
150 *value = val.expect("removing existing value via set_attr, this is not yet supported (TODO)"); // TODO
151 return;
152 }
153
154 if let Some(val) = val {
155 self.attributes.insert(name, val);
156 }
157 }
158
159 /// Returns whether the element has the given name and namespace.
160 ///
161 /// # Examples
162 ///
163 /// ```
164 /// use minidom::Element;
165 ///
166 /// let elem = Element::builder("name").ns("namespace").build();
167 ///
168 /// assert_eq!(elem.is("name", "namespace"), true);
169 /// assert_eq!(elem.is("name", "wrong"), false);
170 /// assert_eq!(elem.is("wrong", "namespace"), false);
171 /// assert_eq!(elem.is("wrong", "wrong"), false);
172 /// ```
173 pub fn is<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
174 let ns = self.namespace.as_ref().map(String::as_ref);
175 self.name == name.as_ref() && ns == Some(namespace.as_ref())
176 }
177
178 /// Parse a document from an `EventReader`.
179 pub fn from_reader<R: Read>(reader: &mut EventReader<R>) -> Result<Element, Error> {
180 loop {
181 let e = reader.next()?;
182 match e {
183 ReaderEvent::StartElement { name, attributes, namespace } => {
184 let attributes = attributes.into_iter()
185 .map(|o| {
186 (match o.name.prefix {
187 Some(prefix) => format!("{}:{}", prefix, o.name.local_name),
188 None => o.name.local_name
189 },
190 o.value)
191 })
192 .collect();
193 let ns = if let Some(ref prefix) = name.prefix {
194 namespace.get(prefix)
195 }
196 else {
197 namespace.get(NS_NO_PREFIX)
198 }.map(|s| s.to_owned());
199
200 let mut root = Element::new(name.local_name, ns, attributes, Vec::new());
201 root.from_reader_inner(reader)?;
202 return Ok(root);
203 },
204 ReaderEvent::EndDocument => {
205 return Err(Error::EndOfDocument);
206 },
207 _ => () // TODO: may need more errors
208 }
209 }
210 }
211
212 fn from_reader_inner<R: Read>(&mut self, reader: &mut EventReader<R>) -> Result<(), Error> {
213 loop {
214 let e = reader.next()?;
215 match e {
216 ReaderEvent::StartElement { name, attributes, namespace } => {
217 let attributes = attributes.into_iter()
218 .map(|o| {
219 (match o.name.prefix {
220 Some(prefix) => format!("{}:{}", prefix, o.name.local_name),
221 None => o.name.local_name
222 },
223 o.value)
224 })
225 .collect();
226 let ns = if let Some(ref prefix) = name.prefix {
227 namespace.get(prefix)
228 }
229 else {
230 namespace.get(NS_NO_PREFIX)
231 }.map(|s| s.to_owned());
232 let elem = Element::new(name.local_name, ns, attributes, Vec::with_capacity(1));
233 let elem_ref = self.append_child(elem);
234 elem_ref.from_reader_inner(reader)?;
235 },
236 ReaderEvent::EndElement { .. } => {
237 // TODO: may want to check whether we're closing the correct element
238 return Ok(());
239 },
240 ReaderEvent::Characters(s) => {
241 self.append_text_node(s);
242 },
243 ReaderEvent::CData(s) => {
244 self.append_text_node(s);
245 },
246 ReaderEvent::EndDocument => {
247 return Err(Error::EndOfDocument);
248 },
249 _ => (), // TODO: may need to implement more
250 }
251 }
252 }
253
254 /// Output a document to an `EventWriter`.
255 pub fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), Error> {
256 let name = if let Some(ref ns) = self.namespace {
257 Name::qualified(&self.name, &ns, None)
258 }
259 else {
260 Name::local(&self.name)
261 };
262 let mut start = WriterEvent::start_element(name);
263 if let Some(ref ns) = self.namespace {
264 start = start.default_ns(ns.clone());
265 }
266 for attr in &self.attributes { // TODO: I think this could be done a lot more efficiently
267 start = start.attr(Name::local(&attr.0), &attr.1);
268 }
269 writer.write(start)?;
270 for child in &self.children {
271 match *child {
272 Node::Element(ref e) => {
273 e.write_to(writer)?;
274 },
275 Node::Text(ref s) => {
276 writer.write(WriterEvent::characters(s))?;
277 },
278 }
279 }
280 writer.write(WriterEvent::end_element())?;
281 Ok(())
282 }
283
284 /// Returns an iterator over references to the children of this element.
285 ///
286 /// # Examples
287 ///
288 /// ```
289 /// use minidom::Element;
290 ///
291 /// let elem: Element = "<root><child1 /><child2 /><child3 /></root>".parse().unwrap();
292 ///
293 /// let mut iter = elem.children();
294 /// assert_eq!(iter.next().unwrap().name(), "child1");
295 /// assert_eq!(iter.next().unwrap().name(), "child2");
296 /// assert_eq!(iter.next().unwrap().name(), "child3");
297 /// assert_eq!(iter.next(), None);
298 /// ```
299 pub fn children<'a>(&'a self) -> Children<'a> {
300 Children {
301 iter: self.children.iter(),
302 }
303 }
304
305 /// Returns an iterator over mutable references to the children of this element.
306 pub fn children_mut<'a>(&'a mut self) -> ChildrenMut<'a> {
307 ChildrenMut {
308 iter: self.children.iter_mut(),
309 }
310 }
311
312 fn propagate_namespaces(&mut self) {
313 let ns = self.namespace.clone();
314 for child in self.children_mut() {
315 if child.namespace.is_none() {
316 child.namespace = ns.clone();
317 child.propagate_namespaces();
318 }
319 }
320 }
321
322 /// Appends a child node to the `Element`, returning the appended node.
323 ///
324 /// # Examples
325 ///
326 /// ```
327 /// use minidom::Element;
328 ///
329 /// let mut elem = Element::bare("root");
330 ///
331 /// assert_eq!(elem.children().count(), 0);
332 ///
333 /// elem.append_child(Element::bare("child"));
334 ///
335 /// {
336 /// let mut iter = elem.children();
337 /// assert_eq!(iter.next().unwrap().name(), "child");
338 /// assert_eq!(iter.next(), None);
339 /// }
340 ///
341 /// let child = elem.append_child(Element::bare("new"));
342 ///
343 /// assert_eq!(child.name(), "new");
344 /// ```
345 pub fn append_child(&mut self, mut child: Element) -> &mut Element {
346 if child.namespace.is_none() && self.namespace.is_some() {
347 child.namespace = self.namespace.clone();
348 child.propagate_namespaces();
349 }
350 self.children.push(Node::Element(child));
351 if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
352 cld
353 }
354 else {
355 unreachable!()
356 }
357 }
358
359 /// Appends a text node to an `Element`.
360 ///
361 /// # Examples
362 ///
363 /// ```
364 /// use minidom::Element;
365 ///
366 /// let mut elem = Element::bare("node");
367 ///
368 /// assert_eq!(elem.text(), "");
369 ///
370 /// elem.append_text_node("text");
371 ///
372 /// assert_eq!(elem.text(), "text");
373 /// ```
374 pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
375 self.children.push(Node::Text(child.into()));
376 }
377
378 /// Appends a node to an `Element`.
379 ///
380 /// # Examples
381 ///
382 /// ```
383 /// use minidom::{Element, Node};
384 ///
385 /// let mut elem = Element::bare("node");
386 ///
387 /// elem.append_node(Node::Text("hello".to_owned()));
388 ///
389 /// assert_eq!(elem.text(), "hello");
390 /// ```
391 pub fn append_node(&mut self, node: Node) {
392 self.children.push(node);
393 }
394
395 /// Returns the concatenation of all text nodes in the `Element`.
396 ///
397 /// # Examples
398 ///
399 /// ```
400 /// use minidom::Element;
401 ///
402 /// let elem: Element = "<node>hello, world!</node>".parse().unwrap();
403 ///
404 /// assert_eq!(elem.text(), "hello, world!");
405 /// ```
406 pub fn text(&self) -> String {
407 let mut ret = String::new();
408 for fork in &self.children {
409 if let Node::Text(ref s) = *fork {
410 ret += s;
411 }
412 }
413 ret
414 }
415
416 /// Returns a reference to the first child element with the specific name and namespace, if it
417 /// exists in the direct descendants of this `Element`, else returns `None`.
418 ///
419 /// # Examples
420 ///
421 /// ```
422 /// use minidom::Element;
423 ///
424 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
425 ///
426 /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
427 /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
428 /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
429 /// assert_eq!(elem.get_child("c", "ns"), None);
430 /// assert_eq!(elem.get_child("b", "other_ns"), None);
431 /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
432 /// ```
433 pub fn get_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> Option<&Element> {
434 for fork in &self.children {
435 if let Node::Element(ref e) = *fork {
436 if e.is(name.as_ref(), namespace.as_ref()) {
437 return Some(e);
438 }
439 }
440 }
441 None
442 }
443
444 /// Returns a mutable reference to the first child element with the specific name and namespace,
445 /// if it exists in the direct descendants of this `Element`, else returns `None`.
446 pub fn get_child_mut<N: AsRef<str>, NS: AsRef<str>>(&mut self, name: N, namespace: NS) -> Option<&mut Element> {
447 for fork in &mut self.children {
448 if let Node::Element(ref mut e) = *fork {
449 if e.is(name.as_ref(), namespace.as_ref()) {
450 return Some(e);
451 }
452 }
453 }
454 None
455 }
456
457 /// Returns whether a specific child with this name and namespace exists in the direct
458 /// descendants of the `Element`.
459 ///
460 /// # Examples
461 ///
462 /// ```
463 /// use minidom::Element;
464 ///
465 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
466 ///
467 /// assert_eq!(elem.has_child("a", "other_ns"), true);
468 /// assert_eq!(elem.has_child("a", "ns"), true);
469 /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
470 /// assert_eq!(elem.has_child("b", "ns"), true);
471 /// assert_eq!(elem.has_child("b", "other_ns"), false);
472 /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
473 /// ```
474 pub fn has_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
475 self.get_child(name, namespace).is_some()
476 }
477}
478
479/// An iterator over references to children of an `Element`.
480pub struct Children<'a> {
481 iter: slice::Iter<'a, Node>,
482}
483
484impl<'a> Iterator for Children<'a> {
485 type Item = &'a Element;
486
487 fn next(&mut self) -> Option<&'a Element> {
488 while let Some(item) = self.iter.next() {
489 if let Node::Element(ref child) = *item {
490 return Some(child);
491 }
492 }
493 None
494 }
495}
496
497/// An iterator over mutable references to children of an `Element`.
498pub struct ChildrenMut<'a> {
499 iter: slice::IterMut<'a, Node>,
500}
501
502impl<'a> Iterator for ChildrenMut<'a> {
503 type Item = &'a mut Element;
504
505 fn next(&mut self) -> Option<&'a mut Element> {
506 while let Some(item) = self.iter.next() {
507 if let Node::Element(ref mut child) = *item {
508 return Some(child);
509 }
510 }
511 None
512 }
513}
514
515/// A builder for `Element`s.
516pub struct ElementBuilder {
517 root: Element,
518}
519
520impl ElementBuilder {
521 /// Sets the namespace.
522 pub fn ns<S: Into<String>>(mut self, namespace: S) -> ElementBuilder {
523 self.root.namespace = Some(namespace.into());
524 self
525 }
526
527 /// Sets an attribute.
528 pub fn attr<S: Into<String>, V: IntoAttributeValue>(mut self, name: S, value: V) -> ElementBuilder {
529 self.root.set_attr(name, value);
530 self
531 }
532
533 /// Appends anything implementing `IntoElements` into the tree.
534 pub fn append<T: IntoElements>(mut self, into: T) -> ElementBuilder {
535 {
536 let mut emitter = ElementEmitter::new(&mut self.root);
537 into.into_elements(&mut emitter);
538 }
539 self
540 }
541
542 /// Builds the `Element`.
543 pub fn build(self) -> Element {
544 self.root
545 }
546}
547
548#[test]
549fn test_element_new() {
550 use std::iter::FromIterator;
551
552 let elem = Element::new( "name".to_owned()
553 , Some("namespace".to_owned())
554 , BTreeMap::from_iter(vec![ ("name".to_string(), "value".to_string()) ].into_iter() )
555 , Vec::new() );
556
557 assert_eq!(elem.name(), "name");
558 assert_eq!(elem.ns(), Some("namespace"));
559 assert_eq!(elem.attr("name"), Some("value"));
560 assert_eq!(elem.attr("inexistent"), None);
561}