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;
6use std::collections::btree_map;
7
8use std::fmt;
9
10use error::{Error, ErrorKind, Result};
11
12use xml::reader::{XmlEvent as ReaderEvent, EventReader};
13use xml::writer::{XmlEvent as WriterEvent, EventWriter, EmitterConfig};
14use xml::name::Name;
15use xml::namespace::NS_NO_PREFIX;
16
17use std::str::FromStr;
18
19use std::slice;
20
21use convert::{IntoElements, IntoAttributeValue, ElementEmitter};
22
23/// A node in an element tree.
24#[derive(Clone, Debug, PartialEq, Eq)]
25pub enum Node {
26 /// An `Element`.
27 Element(Element),
28 /// A text node.
29 Text(String),
30}
31
32impl Node {
33 /// Turns this into an `Element` if possible, else returns None.
34 ///
35 /// # Examples
36 ///
37 /// ```rust
38 /// use minidom::Node;
39 ///
40 /// let elm = Node::Element("<meow />".parse().unwrap());
41 /// let txt = Node::Text("meow".to_owned());
42 ///
43 /// assert_eq!(elm.as_element().unwrap().name(), "meow");
44 /// assert_eq!(txt.as_element(), None);
45 /// ```
46 pub fn as_element(&self) -> Option<&Element> {
47 match *self {
48 Node::Element(ref e) => Some(e),
49 Node::Text(_) => None,
50 }
51 }
52
53 /// Turns this into a `String` if possible, else returns None.
54 ///
55 /// # Examples
56 ///
57 /// ```rust
58 /// use minidom::Node;
59 ///
60 /// let elm = Node::Element("<meow />".parse().unwrap());
61 /// let txt = Node::Text("meow".to_owned());
62 ///
63 /// assert_eq!(elm.as_text(), None);
64 /// assert_eq!(txt.as_text().unwrap(), "meow");
65 /// ```
66 pub fn as_text(&self) -> Option<&str> {
67 match *self {
68 Node::Element(_) => None,
69 Node::Text(ref s) => Some(s),
70 }
71 }
72}
73
74#[derive(Clone, PartialEq, Eq)]
75/// A struct representing a DOM Element.
76pub struct Element {
77 name: String,
78 namespace: Option<String>,
79 attributes: BTreeMap<String, String>,
80 children: Vec<Node>,
81}
82
83impl<'a> From<&'a Element> for String {
84 fn from(elem: &'a Element) -> String {
85 let mut out = Vec::new();
86 let config = EmitterConfig::new()
87 .write_document_declaration(false);
88 elem.write_to(&mut EventWriter::new_with_config(&mut out, config)).unwrap();
89 String::from_utf8(out).unwrap()
90 }
91}
92
93impl fmt::Debug for Element {
94 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
95 write!(fmt, "{}", String::from(self))?;
96 Ok(())
97 }
98}
99
100impl FromStr for Element {
101 type Err = Error;
102
103 fn from_str(s: &str) -> Result<Element> {
104 let mut reader = EventReader::new(Cursor::new(s));
105 Element::from_reader(&mut reader)
106 }
107}
108
109impl Element {
110 fn new(name: String, namespace: Option<String>, attributes: BTreeMap<String, String>, children: Vec<Node>) -> Element {
111 Element {
112 name: name,
113 namespace: namespace,
114 attributes: attributes,
115 children: children,
116 }
117 }
118
119 /// Return a builder for an `Element` with the given `name`.
120 ///
121 /// # Examples
122 ///
123 /// ```rust
124 /// use minidom::Element;
125 ///
126 /// let elem = Element::builder("name")
127 /// .ns("namespace")
128 /// .attr("name", "value")
129 /// .append("inner")
130 /// .build();
131 ///
132 /// assert_eq!(elem.name(), "name");
133 /// assert_eq!(elem.ns(), Some("namespace"));
134 /// assert_eq!(elem.attr("name"), Some("value"));
135 /// assert_eq!(elem.attr("inexistent"), None);
136 /// assert_eq!(elem.text(), "inner");
137 /// ```
138 pub fn builder<S: Into<String>>(name: S) -> ElementBuilder {
139 ElementBuilder {
140 root: Element::new(name.into(), None, BTreeMap::new(), Vec::new()),
141 }
142 }
143
144 /// Returns a bare minimum `Element` with this name.
145 ///
146 /// # Examples
147 ///
148 /// ```rust
149 /// use minidom::Element;
150 ///
151 /// let bare = Element::bare("name");
152 ///
153 /// assert_eq!(bare.name(), "name");
154 /// assert_eq!(bare.ns(), None);
155 /// assert_eq!(bare.attr("name"), None);
156 /// assert_eq!(bare.text(), "");
157 /// ```
158 pub fn bare<S: Into<String>>(name: S) -> Element {
159 Element {
160 name: name.into(),
161 namespace: None,
162 attributes: BTreeMap::new(),
163 children: Vec::new(),
164 }
165 }
166
167 /// Returns a reference to the name of this element.
168 pub fn name(&self) -> &str {
169 &self.name
170 }
171
172 /// Returns a reference to the namespace of this element, if it has one, else `None`.
173 pub fn ns(&self) -> Option<&str> {
174 self.namespace.as_ref()
175 .map(String::as_ref)
176 }
177
178 /// Returns a reference to the value of the given attribute, if it exists, else `None`.
179 pub fn attr(&self, name: &str) -> Option<&str> {
180 if let Some(value) = self.attributes.get(name) {
181 return Some(value)
182 }
183 None
184 }
185
186 /// Returns an iterator over the attributes of this element.
187 ///
188 /// # Example
189 ///
190 /// ```rust
191 /// use minidom::Element;
192 ///
193 /// let elm: Element = "<elem a=\"b\" />".parse().unwrap();
194 ///
195 /// let mut iter = elm.attrs();
196 ///
197 /// assert_eq!(iter.next().unwrap(), ("a", "b"));
198 /// assert_eq!(iter.next(), None);
199 /// ```
200 pub fn attrs(&self) -> Attrs {
201 Attrs {
202 iter: self.attributes.iter(),
203 }
204 }
205
206 /// Returns an iterator over the attributes of this element, with the value being a mutable
207 /// reference.
208 pub fn attrs_mut(&mut self) -> AttrsMut {
209 AttrsMut {
210 iter: self.attributes.iter_mut(),
211 }
212 }
213
214 /// Modifies the value of an attribute.
215 pub fn set_attr<S: Into<String>, V: IntoAttributeValue>(&mut self, name: S, val: V) {
216 let name = name.into();
217 let val = val.into_attribute_value();
218
219 if let Some(value) = self.attributes.get_mut(&name) {
220 *value = val.expect("removing existing value via set_attr, this is not yet supported (TODO)"); // TODO
221 return;
222 }
223
224 if let Some(val) = val {
225 self.attributes.insert(name, val);
226 }
227 }
228
229 /// Returns whether the element has the given name and namespace.
230 ///
231 /// # Examples
232 ///
233 /// ```rust
234 /// use minidom::Element;
235 ///
236 /// let elem = Element::builder("name").ns("namespace").build();
237 ///
238 /// assert_eq!(elem.is("name", "namespace"), true);
239 /// assert_eq!(elem.is("name", "wrong"), false);
240 /// assert_eq!(elem.is("wrong", "namespace"), false);
241 /// assert_eq!(elem.is("wrong", "wrong"), false);
242 /// ```
243 pub fn is<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
244 let ns = self.namespace.as_ref().map(String::as_ref);
245 self.name == name.as_ref() && ns == Some(namespace.as_ref())
246 }
247
248 /// Parse a document from an `EventReader`.
249 pub fn from_reader<R: Read>(reader: &mut EventReader<R>) -> Result<Element> {
250 loop {
251 let e = reader.next()?;
252 match e {
253 ReaderEvent::StartElement { name, attributes, namespace } => {
254 let attributes = attributes.into_iter()
255 .map(|o| {
256 (match o.name.prefix {
257 Some(prefix) => format!("{}:{}", prefix, o.name.local_name),
258 None => o.name.local_name
259 },
260 o.value)
261 })
262 .collect();
263 let ns = if let Some(ref prefix) = name.prefix {
264 namespace.get(prefix)
265 }
266 else {
267 namespace.get(NS_NO_PREFIX)
268 }.map(|s| s.to_owned());
269
270 let mut root = Element::new(name.local_name, ns, attributes, Vec::new());
271 root.from_reader_inner(reader)?;
272 return Ok(root);
273 },
274 ReaderEvent::EndDocument => {
275 bail!(ErrorKind::EndOfDocument);
276 },
277 _ => () // TODO: may need more errors
278 }
279 }
280 }
281
282 #[cfg_attr(feature = "cargo-clippy", allow(wrong_self_convention))]
283 fn from_reader_inner<R: Read>(&mut self, reader: &mut EventReader<R>) -> Result<()> {
284 loop {
285 let e = reader.next()?;
286 match e {
287 ReaderEvent::StartElement { name, attributes, namespace } => {
288 let attributes = attributes.into_iter()
289 .map(|o| {
290 (match o.name.prefix {
291 Some(prefix) => format!("{}:{}", prefix, o.name.local_name),
292 None => o.name.local_name
293 },
294 o.value)
295 })
296 .collect();
297 let ns = if let Some(ref prefix) = name.prefix {
298 namespace.get(prefix)
299 }
300 else {
301 namespace.get(NS_NO_PREFIX)
302 }.map(|s| s.to_owned());
303 let elem = Element::new(name.local_name, ns, attributes, Vec::with_capacity(1));
304 let elem_ref = self.append_child(elem);
305 elem_ref.from_reader_inner(reader)?;
306 },
307 ReaderEvent::EndElement { .. } => {
308 // TODO: may want to check whether we're closing the correct element
309 return Ok(());
310 },
311 ReaderEvent::Characters(s) | ReaderEvent::CData(s) => {
312 self.append_text_node(s);
313 },
314 ReaderEvent::EndDocument => {
315 bail!(ErrorKind::EndOfDocument);
316 },
317 _ => (), // TODO: may need to implement more
318 }
319 }
320 }
321
322 /// Output a document to an `EventWriter`.
323 pub fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<()> {
324 let name = if let Some(ref ns) = self.namespace {
325 Name::qualified(&self.name, ns, None)
326 }
327 else {
328 Name::local(&self.name)
329 };
330 let mut start = WriterEvent::start_element(name);
331 if let Some(ref ns) = self.namespace {
332 start = start.default_ns(ns.clone());
333 }
334 for attr in &self.attributes { // TODO: I think this could be done a lot more efficiently
335 start = start.attr(Name::local(attr.0), attr.1);
336 }
337 writer.write(start)?;
338 for child in &self.children {
339 match *child {
340 Node::Element(ref e) => {
341 e.write_to(writer)?;
342 },
343 Node::Text(ref s) => {
344 writer.write(WriterEvent::characters(s))?;
345 },
346 }
347 }
348 writer.write(WriterEvent::end_element())?;
349 Ok(())
350 }
351
352 /// Returns an iterator over references to every child node of this element.
353 ///
354 /// # Examples
355 ///
356 /// ```rust
357 /// use minidom::{Element, Node};
358 ///
359 /// let elem: Element = "<root>a<c1 />b<c2 />c</root>".parse().unwrap();
360 ///
361 /// let mut iter = elem.nodes();
362 ///
363 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "a");
364 /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c1");
365 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "b");
366 /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c2");
367 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "c");
368 /// assert_eq!(iter.next(), None);
369 /// ```
370 #[inline] pub fn nodes(&self) -> Nodes {
371 self.children.iter()
372 }
373
374 /// Returns an iterator over mutable references to every child node of this element.
375 #[inline] pub fn nodes_mut(&mut self) -> NodesMut {
376 self.children.iter_mut()
377 }
378
379 /// Returns an iterator over references to every child element of this element.
380 ///
381 /// # Examples
382 ///
383 /// ```rust
384 /// use minidom::Element;
385 ///
386 /// let elem: Element = "<root>hello<child1 />this<child2 />is<child3 />ignored</root>".parse().unwrap();
387 ///
388 /// let mut iter = elem.children();
389 /// assert_eq!(iter.next().unwrap().name(), "child1");
390 /// assert_eq!(iter.next().unwrap().name(), "child2");
391 /// assert_eq!(iter.next().unwrap().name(), "child3");
392 /// assert_eq!(iter.next(), None);
393 /// ```
394 #[inline] pub fn children(&self) -> Children {
395 Children {
396 iter: self.children.iter(),
397 }
398 }
399
400 /// Returns an iterator over mutable references to every child element of this element.
401 #[inline] pub fn children_mut(&mut self) -> ChildrenMut {
402 ChildrenMut {
403 iter: self.children.iter_mut(),
404 }
405 }
406
407 /// Returns an iterator over references to every text node of this element.
408 ///
409 /// # Examples
410 ///
411 /// ```rust
412 /// use minidom::Element;
413 ///
414 /// let elem: Element = "<root>hello<c /> world!</root>".parse().unwrap();
415 ///
416 /// let mut iter = elem.texts();
417 /// assert_eq!(iter.next().unwrap(), "hello");
418 /// assert_eq!(iter.next().unwrap(), " world!");
419 /// assert_eq!(iter.next(), None);
420 /// ```
421 #[inline] pub fn texts(&self) -> Texts {
422 Texts {
423 iter: self.children.iter(),
424 }
425 }
426
427 /// Returns an iterator over mutable references to every text node of this element.
428 #[inline] pub fn texts_mut(&mut self) -> TextsMut {
429 TextsMut {
430 iter: self.children.iter_mut(),
431 }
432 }
433
434 /// Appends a child node to the `Element`, returning the appended node.
435 ///
436 /// # Examples
437 ///
438 /// ```rust
439 /// use minidom::Element;
440 ///
441 /// let mut elem = Element::bare("root");
442 ///
443 /// assert_eq!(elem.children().count(), 0);
444 ///
445 /// elem.append_child(Element::bare("child"));
446 ///
447 /// {
448 /// let mut iter = elem.children();
449 /// assert_eq!(iter.next().unwrap().name(), "child");
450 /// assert_eq!(iter.next(), None);
451 /// }
452 ///
453 /// let child = elem.append_child(Element::bare("new"));
454 ///
455 /// assert_eq!(child.name(), "new");
456 /// ```
457 pub fn append_child(&mut self, mut child: Element) -> &mut Element {
458 if child.namespace.is_none() && self.namespace.is_some() {
459 child.namespace = self.namespace.clone();
460 child.propagate_namespaces();
461 }
462 self.children.push(Node::Element(child));
463 if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
464 cld
465 }
466 else {
467 unreachable!()
468 }
469 }
470
471 fn propagate_namespaces(&mut self) {
472 let ns = self.namespace.clone();
473 for child in self.children_mut() {
474 if child.namespace.is_none() {
475 child.namespace = ns.clone();
476 child.propagate_namespaces();
477 }
478 }
479 }
480
481 /// Appends a text node to an `Element`.
482 ///
483 /// # Examples
484 ///
485 /// ```rust
486 /// use minidom::Element;
487 ///
488 /// let mut elem = Element::bare("node");
489 ///
490 /// assert_eq!(elem.text(), "");
491 ///
492 /// elem.append_text_node("text");
493 ///
494 /// assert_eq!(elem.text(), "text");
495 /// ```
496 pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
497 self.children.push(Node::Text(child.into()));
498 }
499
500 /// Appends a node to an `Element`.
501 ///
502 /// # Examples
503 ///
504 /// ```rust
505 /// use minidom::{Element, Node};
506 ///
507 /// let mut elem = Element::bare("node");
508 ///
509 /// elem.append_node(Node::Text("hello".to_owned()));
510 ///
511 /// assert_eq!(elem.text(), "hello");
512 /// ```
513 pub fn append_node(&mut self, node: Node) {
514 self.children.push(node);
515 }
516
517 /// Returns the concatenation of all text nodes in the `Element`.
518 ///
519 /// # Examples
520 ///
521 /// ```rust
522 /// use minidom::Element;
523 ///
524 /// let elem: Element = "<node>hello,<split /> world!</node>".parse().unwrap();
525 ///
526 /// assert_eq!(elem.text(), "hello, world!");
527 /// ```
528 pub fn text(&self) -> String {
529 self.texts().fold(String::new(), |ret, new| ret + new)
530 }
531
532 /// Returns a reference to the first child element with the specific name and namespace, if it
533 /// exists in the direct descendants of this `Element`, else returns `None`.
534 ///
535 /// # Examples
536 ///
537 /// ```rust
538 /// use minidom::Element;
539 ///
540 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
541 ///
542 /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
543 /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
544 /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
545 /// assert_eq!(elem.get_child("c", "ns"), None);
546 /// assert_eq!(elem.get_child("b", "other_ns"), None);
547 /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
548 /// ```
549 pub fn get_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> Option<&Element> {
550 for fork in &self.children {
551 if let Node::Element(ref e) = *fork {
552 if e.is(name.as_ref(), namespace.as_ref()) {
553 return Some(e);
554 }
555 }
556 }
557 None
558 }
559
560 /// Returns a mutable reference to the first child element with the specific name and namespace,
561 /// if it exists in the direct descendants of this `Element`, else returns `None`.
562 pub fn get_child_mut<N: AsRef<str>, NS: AsRef<str>>(&mut self, name: N, namespace: NS) -> Option<&mut Element> {
563 for fork in &mut self.children {
564 if let Node::Element(ref mut e) = *fork {
565 if e.is(name.as_ref(), namespace.as_ref()) {
566 return Some(e);
567 }
568 }
569 }
570 None
571 }
572
573 /// Returns whether a specific child with this name and namespace exists in the direct
574 /// descendants of the `Element`.
575 ///
576 /// # Examples
577 ///
578 /// ```rust
579 /// use minidom::Element;
580 ///
581 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
582 ///
583 /// assert_eq!(elem.has_child("a", "other_ns"), true);
584 /// assert_eq!(elem.has_child("a", "ns"), true);
585 /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
586 /// assert_eq!(elem.has_child("b", "ns"), true);
587 /// assert_eq!(elem.has_child("b", "other_ns"), false);
588 /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
589 /// ```
590 pub fn has_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
591 self.get_child(name, namespace).is_some()
592 }
593}
594
595/// An iterator over references to child elements of an `Element`.
596pub struct Children<'a> {
597 iter: slice::Iter<'a, Node>,
598}
599
600impl<'a> Iterator for Children<'a> {
601 type Item = &'a Element;
602
603 fn next(&mut self) -> Option<&'a Element> {
604 for item in &mut self.iter {
605 if let Node::Element(ref child) = *item {
606 return Some(child);
607 }
608 }
609 None
610 }
611}
612
613/// An iterator over mutable references to child elements of an `Element`.
614pub struct ChildrenMut<'a> {
615 iter: slice::IterMut<'a, Node>,
616}
617
618impl<'a> Iterator for ChildrenMut<'a> {
619 type Item = &'a mut Element;
620
621 fn next(&mut self) -> Option<&'a mut Element> {
622 for item in &mut self.iter {
623 if let Node::Element(ref mut child) = *item {
624 return Some(child);
625 }
626 }
627 None
628 }
629}
630
631/// An iterator over references to child text nodes of an `Element`.
632pub struct Texts<'a> {
633 iter: slice::Iter<'a, Node>,
634}
635
636impl<'a> Iterator for Texts<'a> {
637 type Item = &'a str;
638
639 fn next(&mut self) -> Option<&'a str> {
640 for item in &mut self.iter {
641 if let Node::Text(ref child) = *item {
642 return Some(child);
643 }
644 }
645 None
646 }
647}
648
649/// An iterator over mutable references to child text nodes of an `Element`.
650pub struct TextsMut<'a> {
651 iter: slice::IterMut<'a, Node>,
652}
653
654impl<'a> Iterator for TextsMut<'a> {
655 type Item = &'a mut String;
656
657 fn next(&mut self) -> Option<&'a mut String> {
658 for item in &mut self.iter {
659 if let Node::Text(ref mut child) = *item {
660 return Some(child);
661 }
662 }
663 None
664 }
665}
666
667/// An iterator over references to all child nodes of an `Element`.
668pub type Nodes<'a> = slice::Iter<'a, Node>;
669
670/// An iterator over mutable references to all child nodes of an `Element`.
671pub type NodesMut<'a> = slice::IterMut<'a, Node>;
672
673/// An iterator over the attributes of an `Element`.
674pub struct Attrs<'a> {
675 iter: btree_map::Iter<'a, String, String>,
676}
677
678impl<'a> Iterator for Attrs<'a> {
679 type Item = (&'a str, &'a str);
680
681 fn next(&mut self) -> Option<Self::Item> {
682 self.iter.next().map(|(x, y)| (x.as_ref(), y.as_ref()))
683 }
684}
685
686/// An iterator over the attributes of an `Element`, with the values mutable.
687pub struct AttrsMut<'a> {
688 iter: btree_map::IterMut<'a, String, String>,
689}
690
691impl<'a> Iterator for AttrsMut<'a> {
692 type Item = (&'a str, &'a mut String);
693
694 fn next(&mut self) -> Option<Self::Item> {
695 self.iter.next().map(|(x, y)| (x.as_ref(), y))
696 }
697}
698
699/// A builder for `Element`s.
700pub struct ElementBuilder {
701 root: Element,
702}
703
704impl ElementBuilder {
705 /// Sets the namespace.
706 pub fn ns<S: Into<String>>(mut self, namespace: S) -> ElementBuilder {
707 self.root.namespace = Some(namespace.into());
708 self
709 }
710
711 /// Sets an attribute.
712 pub fn attr<S: Into<String>, V: IntoAttributeValue>(mut self, name: S, value: V) -> ElementBuilder {
713 self.root.set_attr(name, value);
714 self
715 }
716
717 /// Appends anything implementing `IntoElements` into the tree.
718 pub fn append<T: IntoElements>(mut self, into: T) -> ElementBuilder {
719 {
720 let mut emitter = ElementEmitter::new(&mut self.root);
721 into.into_elements(&mut emitter);
722 }
723 self
724 }
725
726 /// Builds the `Element`.
727 pub fn build(self) -> Element {
728 self.root
729 }
730}
731
732#[test]
733fn test_element_new() {
734 use std::iter::FromIterator;
735
736 let elem = Element::new( "name".to_owned()
737 , Some("namespace".to_owned())
738 , BTreeMap::from_iter(vec![ ("name".to_string(), "value".to_string()) ].into_iter() )
739 , Vec::new() );
740
741 assert_eq!(elem.name(), "name");
742 assert_eq!(elem.ns(), Some("namespace"));
743 assert_eq!(elem.attr("name"), Some("value"));
744 assert_eq!(elem.attr("inexistent"), None);
745}