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;
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<'a>(&'a self) -> Option<&'a 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<'a>(&'a self) -> Option<&'a 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, Error> {
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<'a>(&'a self) -> Attrs<'a> {
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<'a>(&'a mut self) -> AttrsMut<'a> {
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, Error> {
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 return Err(Error::EndOfDocument);
276 },
277 _ => () // TODO: may need more errors
278 }
279 }
280 }
281
282 fn from_reader_inner<R: Read>(&mut self, reader: &mut EventReader<R>) -> Result<(), Error> {
283 loop {
284 let e = reader.next()?;
285 match e {
286 ReaderEvent::StartElement { name, attributes, namespace } => {
287 let attributes = attributes.into_iter()
288 .map(|o| {
289 (match o.name.prefix {
290 Some(prefix) => format!("{}:{}", prefix, o.name.local_name),
291 None => o.name.local_name
292 },
293 o.value)
294 })
295 .collect();
296 let ns = if let Some(ref prefix) = name.prefix {
297 namespace.get(prefix)
298 }
299 else {
300 namespace.get(NS_NO_PREFIX)
301 }.map(|s| s.to_owned());
302 let elem = Element::new(name.local_name, ns, attributes, Vec::with_capacity(1));
303 let elem_ref = self.append_child(elem);
304 elem_ref.from_reader_inner(reader)?;
305 },
306 ReaderEvent::EndElement { .. } => {
307 // TODO: may want to check whether we're closing the correct element
308 return Ok(());
309 },
310 ReaderEvent::Characters(s) => {
311 self.append_text_node(s);
312 },
313 ReaderEvent::CData(s) => {
314 self.append_text_node(s);
315 },
316 ReaderEvent::EndDocument => {
317 return Err(Error::EndOfDocument);
318 },
319 _ => (), // TODO: may need to implement more
320 }
321 }
322 }
323
324 /// Output a document to an `EventWriter`.
325 pub fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), Error> {
326 let name = if let Some(ref ns) = self.namespace {
327 Name::qualified(&self.name, &ns, None)
328 }
329 else {
330 Name::local(&self.name)
331 };
332 let mut start = WriterEvent::start_element(name);
333 if let Some(ref ns) = self.namespace {
334 start = start.default_ns(ns.clone());
335 }
336 for attr in &self.attributes { // TODO: I think this could be done a lot more efficiently
337 start = start.attr(Name::local(&attr.0), &attr.1);
338 }
339 writer.write(start)?;
340 for child in &self.children {
341 match *child {
342 Node::Element(ref e) => {
343 e.write_to(writer)?;
344 },
345 Node::Text(ref s) => {
346 writer.write(WriterEvent::characters(s))?;
347 },
348 }
349 }
350 writer.write(WriterEvent::end_element())?;
351 Ok(())
352 }
353
354 /// Returns an iterator over references to every child node of this element.
355 ///
356 /// # Examples
357 ///
358 /// ```rust
359 /// use minidom::{Element, Node};
360 ///
361 /// let elem: Element = "<root>a<c1 />b<c2 />c</root>".parse().unwrap();
362 ///
363 /// let mut iter = elem.nodes();
364 ///
365 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "a");
366 /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c1");
367 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "b");
368 /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c2");
369 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "c");
370 /// assert_eq!(iter.next(), None);
371 /// ```
372 #[inline] pub fn nodes<'a>(&'a self) -> Nodes<'a> {
373 self.children.iter()
374 }
375
376 /// Returns an iterator over mutable references to every child node of this element.
377 #[inline] pub fn nodes_mut<'a>(&'a mut self) -> NodesMut<'a> {
378 self.children.iter_mut()
379 }
380
381 /// Returns an iterator over references to every child element of this element.
382 ///
383 /// # Examples
384 ///
385 /// ```rust
386 /// use minidom::Element;
387 ///
388 /// let elem: Element = "<root>hello<child1 />this<child2 />is<child3 />ignored</root>".parse().unwrap();
389 ///
390 /// let mut iter = elem.children();
391 /// assert_eq!(iter.next().unwrap().name(), "child1");
392 /// assert_eq!(iter.next().unwrap().name(), "child2");
393 /// assert_eq!(iter.next().unwrap().name(), "child3");
394 /// assert_eq!(iter.next(), None);
395 /// ```
396 #[inline] pub fn children<'a>(&'a self) -> Children<'a> {
397 Children {
398 iter: self.children.iter(),
399 }
400 }
401
402 /// Returns an iterator over mutable references to every child element of this element.
403 #[inline] pub fn children_mut<'a>(&'a mut self) -> ChildrenMut<'a> {
404 ChildrenMut {
405 iter: self.children.iter_mut(),
406 }
407 }
408
409 /// Returns an iterator over references to every text node of this element.
410 ///
411 /// # Examples
412 ///
413 /// ```rust
414 /// use minidom::Element;
415 ///
416 /// let elem: Element = "<root>hello<c /> world!</root>".parse().unwrap();
417 ///
418 /// let mut iter = elem.texts();
419 /// assert_eq!(iter.next().unwrap(), "hello");
420 /// assert_eq!(iter.next().unwrap(), " world!");
421 /// assert_eq!(iter.next(), None);
422 /// ```
423 #[inline] pub fn texts<'a>(&'a self) -> Texts<'a> {
424 Texts {
425 iter: self.children.iter(),
426 }
427 }
428
429 /// Returns an iterator over mutable references to every text node of this element.
430 #[inline] pub fn texts_mut<'a>(&'a mut self) -> TextsMut<'a> {
431 TextsMut {
432 iter: self.children.iter_mut(),
433 }
434 }
435
436 /// Appends a child node to the `Element`, returning the appended node.
437 ///
438 /// # Examples
439 ///
440 /// ```rust
441 /// use minidom::Element;
442 ///
443 /// let mut elem = Element::bare("root");
444 ///
445 /// assert_eq!(elem.children().count(), 0);
446 ///
447 /// elem.append_child(Element::bare("child"));
448 ///
449 /// {
450 /// let mut iter = elem.children();
451 /// assert_eq!(iter.next().unwrap().name(), "child");
452 /// assert_eq!(iter.next(), None);
453 /// }
454 ///
455 /// let child = elem.append_child(Element::bare("new"));
456 ///
457 /// assert_eq!(child.name(), "new");
458 /// ```
459 pub fn append_child(&mut self, mut child: Element) -> &mut Element {
460 if child.namespace.is_none() && self.namespace.is_some() {
461 child.namespace = self.namespace.clone();
462 child.propagate_namespaces();
463 }
464 self.children.push(Node::Element(child));
465 if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
466 cld
467 }
468 else {
469 unreachable!()
470 }
471 }
472
473 fn propagate_namespaces(&mut self) {
474 let ns = self.namespace.clone();
475 for child in self.children_mut() {
476 if child.namespace.is_none() {
477 child.namespace = ns.clone();
478 child.propagate_namespaces();
479 }
480 }
481 }
482
483 /// Appends a text node to an `Element`.
484 ///
485 /// # Examples
486 ///
487 /// ```rust
488 /// use minidom::Element;
489 ///
490 /// let mut elem = Element::bare("node");
491 ///
492 /// assert_eq!(elem.text(), "");
493 ///
494 /// elem.append_text_node("text");
495 ///
496 /// assert_eq!(elem.text(), "text");
497 /// ```
498 pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
499 self.children.push(Node::Text(child.into()));
500 }
501
502 /// Appends a node to an `Element`.
503 ///
504 /// # Examples
505 ///
506 /// ```rust
507 /// use minidom::{Element, Node};
508 ///
509 /// let mut elem = Element::bare("node");
510 ///
511 /// elem.append_node(Node::Text("hello".to_owned()));
512 ///
513 /// assert_eq!(elem.text(), "hello");
514 /// ```
515 pub fn append_node(&mut self, node: Node) {
516 self.children.push(node);
517 }
518
519 /// Returns the concatenation of all text nodes in the `Element`.
520 ///
521 /// # Examples
522 ///
523 /// ```rust
524 /// use minidom::Element;
525 ///
526 /// let elem: Element = "<node>hello,<split /> world!</node>".parse().unwrap();
527 ///
528 /// assert_eq!(elem.text(), "hello, world!");
529 /// ```
530 pub fn text(&self) -> String {
531 self.texts().fold(String::new(), |ret, new| ret + new)
532 }
533
534 /// Returns a reference to the first child element with the specific name and namespace, if it
535 /// exists in the direct descendants of this `Element`, else returns `None`.
536 ///
537 /// # Examples
538 ///
539 /// ```rust
540 /// use minidom::Element;
541 ///
542 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
543 ///
544 /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
545 /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
546 /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
547 /// assert_eq!(elem.get_child("c", "ns"), None);
548 /// assert_eq!(elem.get_child("b", "other_ns"), None);
549 /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
550 /// ```
551 pub fn get_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> Option<&Element> {
552 for fork in &self.children {
553 if let Node::Element(ref e) = *fork {
554 if e.is(name.as_ref(), namespace.as_ref()) {
555 return Some(e);
556 }
557 }
558 }
559 None
560 }
561
562 /// Returns a mutable reference to the first child element with the specific name and namespace,
563 /// if it exists in the direct descendants of this `Element`, else returns `None`.
564 pub fn get_child_mut<N: AsRef<str>, NS: AsRef<str>>(&mut self, name: N, namespace: NS) -> Option<&mut Element> {
565 for fork in &mut self.children {
566 if let Node::Element(ref mut e) = *fork {
567 if e.is(name.as_ref(), namespace.as_ref()) {
568 return Some(e);
569 }
570 }
571 }
572 None
573 }
574
575 /// Returns whether a specific child with this name and namespace exists in the direct
576 /// descendants of the `Element`.
577 ///
578 /// # Examples
579 ///
580 /// ```rust
581 /// use minidom::Element;
582 ///
583 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
584 ///
585 /// assert_eq!(elem.has_child("a", "other_ns"), true);
586 /// assert_eq!(elem.has_child("a", "ns"), true);
587 /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
588 /// assert_eq!(elem.has_child("b", "ns"), true);
589 /// assert_eq!(elem.has_child("b", "other_ns"), false);
590 /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
591 /// ```
592 pub fn has_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
593 self.get_child(name, namespace).is_some()
594 }
595}
596
597/// An iterator over references to child elements of an `Element`.
598pub struct Children<'a> {
599 iter: slice::Iter<'a, Node>,
600}
601
602impl<'a> Iterator for Children<'a> {
603 type Item = &'a Element;
604
605 fn next(&mut self) -> Option<&'a Element> {
606 while let Some(item) = self.iter.next() {
607 if let Node::Element(ref child) = *item {
608 return Some(child);
609 }
610 }
611 None
612 }
613}
614
615/// An iterator over mutable references to child elements of an `Element`.
616pub struct ChildrenMut<'a> {
617 iter: slice::IterMut<'a, Node>,
618}
619
620impl<'a> Iterator for ChildrenMut<'a> {
621 type Item = &'a mut Element;
622
623 fn next(&mut self) -> Option<&'a mut Element> {
624 while let Some(item) = self.iter.next() {
625 if let Node::Element(ref mut child) = *item {
626 return Some(child);
627 }
628 }
629 None
630 }
631}
632
633/// An iterator over references to child text nodes of an `Element`.
634pub struct Texts<'a> {
635 iter: slice::Iter<'a, Node>,
636}
637
638impl<'a> Iterator for Texts<'a> {
639 type Item = &'a str;
640
641 fn next(&mut self) -> Option<&'a str> {
642 while let Some(item) = self.iter.next() {
643 if let Node::Text(ref child) = *item {
644 return Some(child);
645 }
646 }
647 None
648 }
649}
650
651/// An iterator over mutable references to child text nodes of an `Element`.
652pub struct TextsMut<'a> {
653 iter: slice::IterMut<'a, Node>,
654}
655
656impl<'a> Iterator for TextsMut<'a> {
657 type Item = &'a mut String;
658
659 fn next(&mut self) -> Option<&'a mut String> {
660 while let Some(item) = self.iter.next() {
661 if let Node::Text(ref mut child) = *item {
662 return Some(child);
663 }
664 }
665 None
666 }
667}
668
669/// An iterator over references to all child nodes of an `Element`.
670pub type Nodes<'a> = slice::Iter<'a, Node>;
671
672/// An iterator over mutable references to all child nodes of an `Element`.
673pub type NodesMut<'a> = slice::IterMut<'a, Node>;
674
675/// An iterator over the attributes of an `Element`.
676pub struct Attrs<'a> {
677 iter: btree_map::Iter<'a, String, String>,
678}
679
680impl<'a> Iterator for Attrs<'a> {
681 type Item = (&'a str, &'a str);
682
683 fn next(&mut self) -> Option<Self::Item> {
684 self.iter.next().map(|(x, y)| (x.as_ref(), y.as_ref()))
685 }
686}
687
688/// An iterator over the attributes of an `Element`, with the values mutable.
689pub struct AttrsMut<'a> {
690 iter: btree_map::IterMut<'a, String, String>,
691}
692
693impl<'a> Iterator for AttrsMut<'a> {
694 type Item = (&'a str, &'a mut String);
695
696 fn next(&mut self) -> Option<Self::Item> {
697 self.iter.next().map(|(x, y)| (x.as_ref(), y))
698 }
699}
700
701/// A builder for `Element`s.
702pub struct ElementBuilder {
703 root: Element,
704}
705
706impl ElementBuilder {
707 /// Sets the namespace.
708 pub fn ns<S: Into<String>>(mut self, namespace: S) -> ElementBuilder {
709 self.root.namespace = Some(namespace.into());
710 self
711 }
712
713 /// Sets an attribute.
714 pub fn attr<S: Into<String>, V: IntoAttributeValue>(mut self, name: S, value: V) -> ElementBuilder {
715 self.root.set_attr(name, value);
716 self
717 }
718
719 /// Appends anything implementing `IntoElements` into the tree.
720 pub fn append<T: IntoElements>(mut self, into: T) -> ElementBuilder {
721 {
722 let mut emitter = ElementEmitter::new(&mut self.root);
723 into.into_elements(&mut emitter);
724 }
725 self
726 }
727
728 /// Builds the `Element`.
729 pub fn build(self) -> Element {
730 self.root
731 }
732}
733
734#[test]
735fn test_element_new() {
736 use std::iter::FromIterator;
737
738 let elem = Element::new( "name".to_owned()
739 , Some("namespace".to_owned())
740 , BTreeMap::from_iter(vec![ ("name".to_string(), "value".to_string()) ].into_iter() )
741 , Vec::new() );
742
743 assert_eq!(elem.name(), "name");
744 assert_eq!(elem.ns(), Some("namespace"));
745 assert_eq!(elem.attr("name"), Some("value"));
746 assert_eq!(elem.attr("inexistent"), None);
747}