1//! Provides an `Element` type, which represents DOM nodes, and a builder to create them with.
2
3use std::io:: Write;
4use std::collections::{btree_map, BTreeMap};
5
6use std::str;
7use std::rc::Rc;
8use std::borrow::Cow;
9
10use error::{Error, Result};
11
12use quick_xml::Reader as EventReader;
13use quick_xml::Writer as EventWriter;
14use quick_xml::events::{Event, BytesStart, BytesEnd, BytesText, BytesDecl};
15
16use std::io::BufRead;
17
18use std::str::FromStr;
19
20use std::slice;
21
22use convert::IntoAttributeValue;
23use namespace_set::NamespaceSet;
24
25/// helper function to escape a `&[u8]` and replace all
26/// xml special characters (<, >, &, ', ") with their corresponding
27/// xml escaped value.
28pub fn escape(raw: &[u8]) -> Cow<[u8]> {
29 let mut escapes: Vec<(usize, &'static [u8])> = Vec::new();
30 let mut bytes = raw.iter();
31 fn to_escape(b: u8) -> bool {
32 match b {
33 b'<' | b'>' | b'\'' | b'&' | b'"' => true,
34 _ => false,
35 }
36 }
37
38 let mut loc = 0;
39 while let Some(i) = bytes.position(|&b| to_escape(b)) {
40 loc += i;
41 match raw[loc] {
42 b'<' => escapes.push((loc, b"<")),
43 b'>' => escapes.push((loc, b">")),
44 b'\'' => escapes.push((loc, b"'")),
45 b'&' => escapes.push((loc, b"&")),
46 b'"' => escapes.push((loc, b""")),
47 _ => unreachable!("Only '<', '>','\', '&' and '\"' are escaped"),
48 }
49 loc += 1;
50 }
51
52 if escapes.is_empty() {
53 Cow::Borrowed(raw)
54 } else {
55 let len = raw.len();
56 let mut v = Vec::with_capacity(len);
57 let mut start = 0;
58 for (i, r) in escapes {
59 v.extend_from_slice(&raw[start..i]);
60 v.extend_from_slice(r);
61 start = i + 1;
62 }
63
64 if start < len {
65 v.extend_from_slice(&raw[start..]);
66 }
67 Cow::Owned(v)
68 }
69}
70
71/// A node in an element tree.
72#[derive(Clone, Debug, PartialEq, Eq)]
73pub enum Node {
74 /// An `Element`.
75 Element(Element),
76 /// A text node.
77 Text(String),
78 /// A comment node.
79 Comment(String),
80}
81
82impl Node {
83 /// Turns this into a reference to an `Element` if this is an element node.
84 /// Else this returns `None`.
85 ///
86 /// # Examples
87 ///
88 /// ```rust
89 /// use minidom::Node;
90 ///
91 /// let elm = Node::Element("<meow />".parse().unwrap());
92 /// let txt = Node::Text("meow".to_owned());
93 ///
94 /// assert_eq!(elm.as_element().unwrap().name(), "meow");
95 /// assert_eq!(txt.as_element(), None);
96 /// ```
97 pub fn as_element(&self) -> Option<&Element> {
98 match *self {
99 Node::Element(ref e) => Some(e),
100 Node::Text(_) => None,
101 Node::Comment(_) => None,
102 }
103 }
104
105 /// Turns this into a mutable reference of an `Element` if this is an element node.
106 /// Else this returns `None`.
107 ///
108 /// # Examples
109 ///
110 /// ```rust
111 /// use minidom::Node;
112 ///
113 /// let mut elm = Node::Element("<meow />".parse().unwrap());
114 /// let mut txt = Node::Text("meow".to_owned());
115 ///
116 /// assert_eq!(elm.as_element_mut().unwrap().name(), "meow");
117 /// assert_eq!(txt.as_element_mut(), None);
118 /// ```
119 pub fn as_element_mut(&mut self) -> Option<&mut Element> {
120 match *self {
121 Node::Element(ref mut e) => Some(e),
122 Node::Text(_) => None,
123 Node::Comment(_) => None,
124 }
125 }
126
127 /// Turns this into an `Element`, consuming self, if this is an element node.
128 /// Else this returns `None`.
129 ///
130 /// # Examples
131 ///
132 /// ```rust
133 /// use minidom::Node;
134 ///
135 /// let elm = Node::Element("<meow />".parse().unwrap());
136 /// let txt = Node::Text("meow".to_owned());
137 ///
138 /// assert_eq!(elm.into_element().unwrap().name(), "meow");
139 /// assert_eq!(txt.into_element(), None);
140 /// ```
141 pub fn into_element(self) -> Option<Element> {
142 match self {
143 Node::Element(e) => Some(e),
144 Node::Text(_) => None,
145 Node::Comment(_) => None,
146 }
147 }
148
149 /// Turns this into an `&str` if this is a text node.
150 /// Else this returns `None`.
151 ///
152 /// # Examples
153 ///
154 /// ```rust
155 /// use minidom::Node;
156 ///
157 /// let elm = Node::Element("<meow />".parse().unwrap());
158 /// let txt = Node::Text("meow".to_owned());
159 ///
160 /// assert_eq!(elm.as_text(), None);
161 /// assert_eq!(txt.as_text().unwrap(), "meow");
162 /// ```
163 pub fn as_text(&self) -> Option<&str> {
164 match *self {
165 Node::Element(_) => None,
166 Node::Text(ref s) => Some(s),
167 Node::Comment(_) => None,
168 }
169 }
170
171 /// Turns this into an `&mut String` if this is a text node.
172 /// Else this returns `None`.
173 ///
174 /// # Examples
175 ///
176 /// ```rust
177 /// use minidom::Node;
178 ///
179 /// let mut elm = Node::Element("<meow />".parse().unwrap());
180 /// let mut txt = Node::Text("meow".to_owned());
181 ///
182 /// assert_eq!(elm.as_text_mut(), None);
183 /// {
184 /// let text_mut = txt.as_text_mut().unwrap();
185 /// assert_eq!(text_mut, "meow");
186 /// text_mut.push_str("zies");
187 /// assert_eq!(text_mut, "meowzies");
188 /// }
189 /// assert_eq!(txt.as_text().unwrap(), "meowzies");
190 /// ```
191 pub fn as_text_mut(&mut self) -> Option<&mut String> {
192 match *self {
193 Node::Element(_) => None,
194 Node::Text(ref mut s) => Some(s),
195 Node::Comment(_) => None,
196 }
197 }
198
199 /// Turns this into an `String`, consuming self, if this is a text node.
200 /// Else this returns `None`.
201 ///
202 /// # Examples
203 ///
204 /// ```rust
205 /// use minidom::Node;
206 ///
207 /// let elm = Node::Element("<meow />".parse().unwrap());
208 /// let txt = Node::Text("meow".to_owned());
209 ///
210 /// assert_eq!(elm.into_text(), None);
211 /// assert_eq!(txt.into_text().unwrap(), "meow");
212 /// ```
213 pub fn into_text(self) -> Option<String> {
214 match self {
215 Node::Element(_) => None,
216 Node::Text(s) => Some(s),
217 Node::Comment(_) => None,
218 }
219 }
220
221 fn write_to_inner<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<()>{
222 match *self {
223 Node::Element(ref elmt) => elmt.write_to_inner(writer)?,
224 Node::Text(ref s) => {
225 writer.write_event(Event::Text(BytesText::from_plain_str(s)))?;
226 ()
227 },
228 Node::Comment(ref s) => {
229 writer.write_event(Event::Comment(BytesText::from_plain_str(s)))?;
230 ()
231 },
232 };
233
234 Ok(())
235 }
236}
237
238impl From<Element> for Node {
239 fn from(elm: Element) -> Node {
240 Node::Element(elm)
241 }
242}
243
244impl From<String> for Node {
245 fn from(s: String) -> Node {
246 Node::Text(s)
247 }
248}
249
250impl<'a> From<&'a str> for Node {
251 fn from(s: &'a str) -> Node {
252 Node::Text(s.to_owned())
253 }
254}
255
256impl From<ElementBuilder> for Node {
257 fn from(builder: ElementBuilder) -> Node {
258 Node::Element(builder.build())
259 }
260}
261
262#[derive(Clone, PartialEq, Eq, Debug)]
263/// A struct representing a DOM Element.
264pub struct Element {
265 prefix: Option<String>,
266 name: String,
267 namespaces: Rc<NamespaceSet>,
268 attributes: BTreeMap<String, String>,
269 children: Vec<Node>,
270}
271
272impl<'a> From<&'a Element> for String {
273 fn from(elem: &'a Element) -> String {
274 let mut writer = Vec::new();
275 elem.write_to(&mut writer).unwrap();
276 String::from_utf8(writer).unwrap()
277 }
278}
279
280impl FromStr for Element {
281 type Err = Error;
282
283 fn from_str(s: &str) -> Result<Element> {
284 let mut reader = EventReader::from_str(s);
285 Element::from_reader(&mut reader)
286 }
287}
288
289impl Element {
290 fn new<NS: Into<NamespaceSet>>(name: String, prefix: Option<String>, namespaces: NS, attributes: BTreeMap<String, String>, children: Vec<Node>) -> Element {
291 Element {
292 prefix, name,
293 namespaces: Rc::new(namespaces.into()),
294 attributes: attributes,
295 children: children,
296 }
297 }
298
299 /// Return a builder for an `Element` with the given `name`.
300 ///
301 /// # Examples
302 ///
303 /// ```rust
304 /// use minidom::Element;
305 ///
306 /// let elem = Element::builder("name")
307 /// .ns("namespace")
308 /// .attr("name", "value")
309 /// .append("inner")
310 /// .build();
311 ///
312 /// assert_eq!(elem.name(), "name");
313 /// assert_eq!(elem.ns(), Some("namespace".to_owned()));
314 /// assert_eq!(elem.attr("name"), Some("value"));
315 /// assert_eq!(elem.attr("inexistent"), None);
316 /// assert_eq!(elem.text(), "inner");
317 /// ```
318 pub fn builder<S: AsRef<str>>(name: S) -> ElementBuilder {
319 let (prefix, name) = split_element_name(name).unwrap();
320 ElementBuilder {
321 root: Element::new(name, prefix, None, BTreeMap::new(), Vec::new()),
322 namespaces: Default::default(),
323 }
324 }
325
326 /// Returns a bare minimum `Element` with this name.
327 ///
328 /// # Examples
329 ///
330 /// ```rust
331 /// use minidom::Element;
332 ///
333 /// let bare = Element::bare("name");
334 ///
335 /// assert_eq!(bare.name(), "name");
336 /// assert_eq!(bare.ns(), None);
337 /// assert_eq!(bare.attr("name"), None);
338 /// assert_eq!(bare.text(), "");
339 /// ```
340 pub fn bare<S: Into<String>>(name: S) -> Element {
341 Element {
342 prefix: None,
343 name: name.into(),
344 namespaces: Rc::new(NamespaceSet::default()),
345 attributes: BTreeMap::new(),
346 children: Vec::new(),
347 }
348 }
349
350 /// Returns a reference to the name of this element.
351 pub fn name(&self) -> &str {
352 &self.name
353 }
354
355 /// Returns a reference to the prefix of this element.
356 ///
357 /// # Examples
358 /// ```rust
359 /// use minidom::Element;
360 ///
361 /// let elem = Element::builder("prefix:name")
362 /// .build();
363 ///
364 /// assert_eq!(elem.name(), "name");
365 /// assert_eq!(elem.prefix(), Some("prefix"));
366 /// ```
367 pub fn prefix(&self) -> Option<&str> {
368 self.prefix.as_ref().map(String::as_ref)
369 }
370
371 /// Returns a reference to the namespace of this element, if it has one, else `None`.
372 pub fn ns(&self) -> Option<String> {
373 self.namespaces.get(&self.prefix)
374 }
375
376 /// Returns a reference to the value of the given attribute, if it exists, else `None`.
377 pub fn attr(&self, name: &str) -> Option<&str> {
378 if let Some(value) = self.attributes.get(name) {
379 return Some(value)
380 }
381 None
382 }
383
384 /// Returns an iterator over the attributes of this element.
385 ///
386 /// # Example
387 ///
388 /// ```rust
389 /// use minidom::Element;
390 ///
391 /// let elm: Element = "<elem a=\"b\" />".parse().unwrap();
392 ///
393 /// let mut iter = elm.attrs();
394 ///
395 /// assert_eq!(iter.next().unwrap(), ("a", "b"));
396 /// assert_eq!(iter.next(), None);
397 /// ```
398 pub fn attrs(&self) -> Attrs {
399 Attrs {
400 iter: self.attributes.iter(),
401 }
402 }
403
404 /// Returns an iterator over the attributes of this element, with the value being a mutable
405 /// reference.
406 pub fn attrs_mut(&mut self) -> AttrsMut {
407 AttrsMut {
408 iter: self.attributes.iter_mut(),
409 }
410 }
411
412 /// Modifies the value of an attribute.
413 pub fn set_attr<S: Into<String>, V: IntoAttributeValue>(&mut self, name: S, val: V) {
414 let name = name.into();
415 let val = val.into_attribute_value();
416
417 if let Some(value) = self.attributes.get_mut(&name) {
418 *value = val.expect("removing existing value via set_attr, this is not yet supported (TODO)"); // TODO
419 return;
420 }
421
422 if let Some(val) = val {
423 self.attributes.insert(name, val);
424 }
425 }
426
427 /// Returns whether the element has the given name and namespace.
428 ///
429 /// # Examples
430 ///
431 /// ```rust
432 /// use minidom::Element;
433 ///
434 /// let elem = Element::builder("name").ns("namespace").build();
435 ///
436 /// assert_eq!(elem.is("name", "namespace"), true);
437 /// assert_eq!(elem.is("name", "wrong"), false);
438 /// assert_eq!(elem.is("wrong", "namespace"), false);
439 /// assert_eq!(elem.is("wrong", "wrong"), false);
440 /// ```
441 pub fn is<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
442 self.name == name.as_ref() &&
443 self.has_ns(namespace)
444 }
445
446 /// Returns whether the element has the given namespace.
447 ///
448 /// # Examples
449 ///
450 /// ```rust
451 /// use minidom::Element;
452 ///
453 /// let elem = Element::builder("name").ns("namespace").build();
454 ///
455 /// assert_eq!(elem.has_ns("namespace"), true);
456 /// assert_eq!(elem.has_ns("wrong"), false);
457 /// ```
458 pub fn has_ns<NS: AsRef<str>>(&self, namespace: NS) -> bool {
459 self.namespaces.has(&self.prefix, namespace)
460 }
461
462 /// Parse a document from an `EventReader`.
463 pub fn from_reader<R: BufRead>(reader: &mut EventReader<R>) -> Result<Element> {
464 let mut buf = Vec::new();
465
466 let root: Element = loop {
467 let e = reader.read_event(&mut buf)?;
468 match e {
469 Event::Empty(ref e) | Event::Start(ref e) => {
470 break build_element(reader, e)?;
471 },
472 Event::Eof => {
473 return Err(Error::EndOfDocument);
474 },
475 Event::Text { .. } |
476 Event::End { .. } |
477 Event::Comment { .. } |
478 Event::CData { .. } |
479 Event::Decl { .. } |
480 Event::PI { .. } |
481 Event::DocType { .. } => (), // TODO: may need more errors
482 }
483 };
484
485 let mut stack = vec![root];
486
487 loop {
488 match reader.read_event(&mut buf)? {
489 Event::Empty(ref e) => {
490 let elem = build_element(reader, e)?;
491 // Since there is no Event::End after, directly append it to the current node
492 stack.last_mut().unwrap().append_child(elem);
493 },
494 Event::Start(ref e) => {
495 let elem = build_element(reader, e)?;
496 stack.push(elem);
497 },
498 Event::End(ref e) => {
499 if stack.len() <= 1 {
500 break;
501 }
502 let elem = stack.pop().unwrap();
503 if let Some(to) = stack.last_mut() {
504 // TODO: check whether this is correct, we are comparing &[u8]s, not &strs
505 let elem_name = e.name();
506 let mut split_iter = elem_name.splitn(2, |u| *u == 0x3A);
507 let possible_prefix = split_iter.next().unwrap(); // Can't be empty.
508 match split_iter.next() {
509 Some(name) => {
510 match elem.prefix() {
511 Some(prefix) => {
512 if possible_prefix != prefix.as_bytes() {
513 return Err(Error::InvalidElementClosed);
514 }
515 },
516 None => {
517 return Err(Error::InvalidElementClosed);
518 },
519 }
520 if name != elem.name().as_bytes() {
521 return Err(Error::InvalidElementClosed);
522 }
523 },
524 None => {
525 if elem.prefix().is_some() {
526 return Err(Error::InvalidElementClosed);
527 }
528 if possible_prefix != elem.name().as_bytes() {
529 return Err(Error::InvalidElementClosed);
530 }
531 },
532 }
533 to.append_child(elem);
534 }
535 },
536 Event::Text(s) => {
537 let text = s.unescape_and_decode(reader)?;
538 if text != "" {
539 let mut current_elem = stack.last_mut().unwrap();
540 current_elem.append_text_node(text);
541 }
542 },
543 Event::CData(s) => {
544 let text = reader.decode(&s).into_owned();
545 if text != "" {
546 let mut current_elem = stack.last_mut().unwrap();
547 current_elem.append_text_node(text);
548 }
549 },
550 Event::Eof => {
551 break;
552 },
553 Event::Comment(s) => {
554 let comment = reader.decode(&s).into_owned();
555 if comment != "" {
556 let current_elem = stack.last_mut().unwrap();
557 current_elem.append_comment_node(comment);
558 }
559 },
560 Event::Decl { .. } |
561 Event::PI { .. } |
562 Event::DocType { .. } => (),
563 }
564 }
565 Ok(stack.pop().unwrap())
566 }
567
568 /// Output a document to a `Writer`.
569 pub fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
570 self.to_writer(&mut EventWriter::new(writer))
571 }
572
573 /// Output the document to quick-xml `Writer`
574 pub fn to_writer<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<()> {
575 writer.write_event(Event::Decl(BytesDecl::new(b"1.0", Some(b"utf-8"), None)))?;
576 self.write_to_inner(writer)
577 }
578
579 /// Like `write_to()` but without the `<?xml?>` prelude
580 pub fn write_to_inner<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<()> {
581 let name = match self.prefix {
582 None => Cow::Borrowed(&self.name),
583 Some(ref prefix) => Cow::Owned(format!("{}:{}", prefix, self.name)),
584 };
585
586 let mut start = BytesStart::borrowed(name.as_bytes(), name.len());
587 for (prefix, ns) in self.namespaces.declared_ns() {
588 match *prefix {
589 None => start.push_attribute(("xmlns", ns.as_ref())),
590 Some(ref prefix) => {
591 let key = format!("xmlns:{}", prefix);
592 start.push_attribute((key.as_bytes(), ns.as_bytes()))
593 },
594 }
595 }
596 for (key, value) in &self.attributes {
597 start.push_attribute((key.as_bytes(), escape(value.as_bytes()).as_ref()));
598 }
599
600 if self.children.is_empty() {
601 writer.write_event(Event::Empty(start))?;
602 return Ok(())
603 }
604
605 writer.write_event(Event::Start(start))?;
606
607 for child in &self.children {
608 child.write_to_inner(writer)?;
609 }
610
611 writer.write_event(Event::End(BytesEnd::borrowed(name.as_bytes())))?;
612 Ok(())
613 }
614
615 /// Returns an iterator over references to every child node of this element.
616 ///
617 /// # Examples
618 ///
619 /// ```rust
620 /// use minidom::Element;
621 ///
622 /// let elem: Element = "<root>a<c1 />b<c2 />c</root>".parse().unwrap();
623 ///
624 /// let mut iter = elem.nodes();
625 ///
626 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "a");
627 /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c1");
628 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "b");
629 /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c2");
630 /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "c");
631 /// assert_eq!(iter.next(), None);
632 /// ```
633 #[inline] pub fn nodes(&self) -> Nodes {
634 self.children.iter()
635 }
636
637 /// Returns an iterator over mutable references to every child node of this element.
638 #[inline] pub fn nodes_mut(&mut self) -> NodesMut {
639 self.children.iter_mut()
640 }
641
642 /// Returns an iterator over references to every child element of this element.
643 ///
644 /// # Examples
645 ///
646 /// ```rust
647 /// use minidom::Element;
648 ///
649 /// let elem: Element = "<root>hello<child1 />this<child2 />is<child3 />ignored</root>".parse().unwrap();
650 ///
651 /// let mut iter = elem.children();
652 /// assert_eq!(iter.next().unwrap().name(), "child1");
653 /// assert_eq!(iter.next().unwrap().name(), "child2");
654 /// assert_eq!(iter.next().unwrap().name(), "child3");
655 /// assert_eq!(iter.next(), None);
656 /// ```
657 #[inline] pub fn children(&self) -> Children {
658 Children {
659 iter: self.children.iter(),
660 }
661 }
662
663 /// Returns an iterator over mutable references to every child element of this element.
664 #[inline] pub fn children_mut(&mut self) -> ChildrenMut {
665 ChildrenMut {
666 iter: self.children.iter_mut(),
667 }
668 }
669
670 /// Returns an iterator over references to every text node of this element.
671 ///
672 /// # Examples
673 ///
674 /// ```rust
675 /// use minidom::Element;
676 ///
677 /// let elem: Element = "<root>hello<c /> world!</root>".parse().unwrap();
678 ///
679 /// let mut iter = elem.texts();
680 /// assert_eq!(iter.next().unwrap(), "hello");
681 /// assert_eq!(iter.next().unwrap(), " world!");
682 /// assert_eq!(iter.next(), None);
683 /// ```
684 #[inline] pub fn texts(&self) -> Texts {
685 Texts {
686 iter: self.children.iter(),
687 }
688 }
689
690 /// Returns an iterator over mutable references to every text node of this element.
691 #[inline] pub fn texts_mut(&mut self) -> TextsMut {
692 TextsMut {
693 iter: self.children.iter_mut(),
694 }
695 }
696
697 /// Appends a child node to the `Element`, returning the appended node.
698 ///
699 /// # Examples
700 ///
701 /// ```rust
702 /// use minidom::Element;
703 ///
704 /// let mut elem = Element::bare("root");
705 ///
706 /// assert_eq!(elem.children().count(), 0);
707 ///
708 /// elem.append_child(Element::bare("child"));
709 ///
710 /// {
711 /// let mut iter = elem.children();
712 /// assert_eq!(iter.next().unwrap().name(), "child");
713 /// assert_eq!(iter.next(), None);
714 /// }
715 ///
716 /// let child = elem.append_child(Element::bare("new"));
717 ///
718 /// assert_eq!(child.name(), "new");
719 /// ```
720 pub fn append_child(&mut self, child: Element) -> &mut Element {
721 child.namespaces.set_parent(Rc::clone(&self.namespaces));
722
723 self.children.push(Node::Element(child));
724 if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
725 cld
726 } else {
727 unreachable!()
728 }
729 }
730
731 /// Appends a text node to an `Element`.
732 ///
733 /// # Examples
734 ///
735 /// ```rust
736 /// use minidom::Element;
737 ///
738 /// let mut elem = Element::bare("node");
739 ///
740 /// assert_eq!(elem.text(), "");
741 ///
742 /// elem.append_text_node("text");
743 ///
744 /// assert_eq!(elem.text(), "text");
745 /// ```
746 pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
747 self.children.push(Node::Text(child.into()));
748 }
749
750 /// Appends a comment node to an `Element`.
751 ///
752 /// # Examples
753 ///
754 /// ```rust
755 /// use minidom::Element;
756 ///
757 /// let mut elem = Element::bare("node");
758 ///
759 /// elem.append_comment_node("comment");
760 /// ```
761 pub fn append_comment_node<S: Into<String>>(&mut self, child: S) {
762 self.children.push(Node::Comment(child.into()));
763 }
764
765 /// Appends a node to an `Element`.
766 ///
767 /// # Examples
768 ///
769 /// ```rust
770 /// use minidom::{Element, Node};
771 ///
772 /// let mut elem = Element::bare("node");
773 ///
774 /// elem.append_node(Node::Text("hello".to_owned()));
775 ///
776 /// assert_eq!(elem.text(), "hello");
777 /// ```
778 pub fn append_node(&mut self, node: Node) {
779 self.children.push(node);
780 }
781
782 /// Returns the concatenation of all text nodes in the `Element`.
783 ///
784 /// # Examples
785 ///
786 /// ```rust
787 /// use minidom::Element;
788 ///
789 /// let elem: Element = "<node>hello,<split /> world!</node>".parse().unwrap();
790 ///
791 /// assert_eq!(elem.text(), "hello, world!");
792 /// ```
793 pub fn text(&self) -> String {
794 self.texts().fold(String::new(), |ret, new| ret + new)
795 }
796
797 /// Returns a reference to the first child element with the specific name and namespace, if it
798 /// exists in the direct descendants of this `Element`, else returns `None`.
799 ///
800 /// # Examples
801 ///
802 /// ```rust
803 /// use minidom::Element;
804 ///
805 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
806 ///
807 /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
808 /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
809 /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
810 /// assert_eq!(elem.get_child("c", "ns"), None);
811 /// assert_eq!(elem.get_child("b", "other_ns"), None);
812 /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
813 /// ```
814 pub fn get_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> Option<&Element> {
815 for fork in &self.children {
816 if let Node::Element(ref e) = *fork {
817 if e.is(name.as_ref(), namespace.as_ref()) {
818 return Some(e);
819 }
820 }
821 }
822 None
823 }
824
825 /// Returns a mutable reference to the first child element with the specific name and namespace,
826 /// if it exists in the direct descendants of this `Element`, else returns `None`.
827 pub fn get_child_mut<N: AsRef<str>, NS: AsRef<str>>(&mut self, name: N, namespace: NS) -> Option<&mut Element> {
828 for fork in &mut self.children {
829 if let Node::Element(ref mut e) = *fork {
830 if e.is(name.as_ref(), namespace.as_ref()) {
831 return Some(e);
832 }
833 }
834 }
835 None
836 }
837
838 /// Returns whether a specific child with this name and namespace exists in the direct
839 /// descendants of the `Element`.
840 ///
841 /// # Examples
842 ///
843 /// ```rust
844 /// use minidom::Element;
845 ///
846 /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
847 ///
848 /// assert_eq!(elem.has_child("a", "other_ns"), true);
849 /// assert_eq!(elem.has_child("a", "ns"), true);
850 /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
851 /// assert_eq!(elem.has_child("b", "ns"), true);
852 /// assert_eq!(elem.has_child("b", "other_ns"), false);
853 /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
854 /// ```
855 pub fn has_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
856 self.get_child(name, namespace).is_some()
857 }
858
859 /// Removes the first child with this name and namespace, if it exists, and returns an
860 /// `Option<Element>` containing this child if it succeeds.
861 /// Returns `None` if no child matches this name and namespace.
862 ///
863 /// # Examples
864 ///
865 /// ```rust
866 /// use minidom::Element;
867 ///
868 /// let mut elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
869 ///
870 /// assert!(elem.remove_child("a", "ns").unwrap().is("a", "ns"));
871 /// assert!(elem.remove_child("a", "ns").is_none());
872 /// assert!(elem.remove_child("inexistent", "inexistent").is_none());
873 /// ```
874 pub fn remove_child<N: AsRef<str>, NS: AsRef<str>>(&mut self, name: N, namespace: NS) -> Option<Element> {
875 let name = name.as_ref();
876 let namespace = namespace.as_ref();
877 let idx = self.children.iter().position(|x| {
878 if let Node::Element(ref elm) = x {
879 elm.is(name, namespace)
880 } else {
881 false
882 }
883 })?;
884 self.children.remove(idx).into_element()
885 }
886}
887
888fn split_element_name<S: AsRef<str>>(s: S) -> Result<(Option<String>, String)> {
889 let name_parts = s.as_ref().split(':').collect::<Vec<&str>>();
890 match name_parts.len() {
891 2 => Ok((Some(name_parts[0].to_owned()), name_parts[1].to_owned())),
892 1 => Ok((None, name_parts[0].to_owned())),
893 _ => Err(Error::InvalidElement),
894 }
895}
896
897fn build_element<R: BufRead>(reader: &EventReader<R>, event: &BytesStart) -> Result<Element> {
898 let mut namespaces = BTreeMap::new();
899 let attributes = event.attributes()
900 .map(|o| {
901 let o = o?;
902 let key = str::from_utf8(o.key)?.to_owned();
903 let value = o.unescape_and_decode_value(reader)?;
904 Ok((key, value))
905 })
906 .filter(|o| {
907 match *o {
908 Ok((ref key, ref value)) if key == "xmlns" => {
909 namespaces.insert(None, value.to_owned());
910 false
911 },
912 Ok((ref key, ref value)) if key.starts_with("xmlns:") => {
913 namespaces.insert(Some(key[6..].to_owned()), value.to_owned());
914 false
915 },
916 _ => true,
917 }
918 })
919 .collect::<Result<BTreeMap<String, String>>>()?;
920
921 let (prefix, name) = split_element_name(str::from_utf8(event.name())?)?;
922 let element = Element::new(name, prefix, namespaces, attributes, Vec::new());
923 Ok(element)
924}
925
926/// An iterator over references to child elements of an `Element`.
927pub struct Children<'a> {
928 iter: slice::Iter<'a, Node>,
929}
930
931impl<'a> Iterator for Children<'a> {
932 type Item = &'a Element;
933
934 fn next(&mut self) -> Option<&'a Element> {
935 for item in &mut self.iter {
936 if let Node::Element(ref child) = *item {
937 return Some(child);
938 }
939 }
940 None
941 }
942}
943
944/// An iterator over mutable references to child elements of an `Element`.
945pub struct ChildrenMut<'a> {
946 iter: slice::IterMut<'a, Node>,
947}
948
949impl<'a> Iterator for ChildrenMut<'a> {
950 type Item = &'a mut Element;
951
952 fn next(&mut self) -> Option<&'a mut Element> {
953 for item in &mut self.iter {
954 if let Node::Element(ref mut child) = *item {
955 return Some(child);
956 }
957 }
958 None
959 }
960}
961
962/// An iterator over references to child text nodes of an `Element`.
963pub struct Texts<'a> {
964 iter: slice::Iter<'a, Node>,
965}
966
967impl<'a> Iterator for Texts<'a> {
968 type Item = &'a str;
969
970 fn next(&mut self) -> Option<&'a str> {
971 for item in &mut self.iter {
972 if let Node::Text(ref child) = *item {
973 return Some(child);
974 }
975 }
976 None
977 }
978}
979
980/// An iterator over mutable references to child text nodes of an `Element`.
981pub struct TextsMut<'a> {
982 iter: slice::IterMut<'a, Node>,
983}
984
985impl<'a> Iterator for TextsMut<'a> {
986 type Item = &'a mut String;
987
988 fn next(&mut self) -> Option<&'a mut String> {
989 for item in &mut self.iter {
990 if let Node::Text(ref mut child) = *item {
991 return Some(child);
992 }
993 }
994 None
995 }
996}
997
998/// An iterator over references to all child nodes of an `Element`.
999pub type Nodes<'a> = slice::Iter<'a, Node>;
1000
1001/// An iterator over mutable references to all child nodes of an `Element`.
1002pub type NodesMut<'a> = slice::IterMut<'a, Node>;
1003
1004/// An iterator over the attributes of an `Element`.
1005pub struct Attrs<'a> {
1006 iter: btree_map::Iter<'a, String, String>,
1007}
1008
1009impl<'a> Iterator for Attrs<'a> {
1010 type Item = (&'a str, &'a str);
1011
1012 fn next(&mut self) -> Option<Self::Item> {
1013 self.iter.next().map(|(x, y)| (x.as_ref(), y.as_ref()))
1014 }
1015}
1016
1017/// An iterator over the attributes of an `Element`, with the values mutable.
1018pub struct AttrsMut<'a> {
1019 iter: btree_map::IterMut<'a, String, String>,
1020}
1021
1022impl<'a> Iterator for AttrsMut<'a> {
1023 type Item = (&'a str, &'a mut String);
1024
1025 fn next(&mut self) -> Option<Self::Item> {
1026 self.iter.next().map(|(x, y)| (x.as_ref(), y))
1027 }
1028}
1029
1030/// A builder for `Element`s.
1031pub struct ElementBuilder {
1032 root: Element,
1033 namespaces: BTreeMap<Option<String>, String>,
1034}
1035
1036impl ElementBuilder {
1037 /// Sets the namespace.
1038 pub fn ns<S: Into<String>>(mut self, namespace: S) -> ElementBuilder {
1039 self.namespaces
1040 .insert(self.root.prefix.clone(), namespace.into());
1041 self
1042 }
1043
1044 /// Sets an attribute.
1045 pub fn attr<S: Into<String>, V: IntoAttributeValue>(mut self, name: S, value: V) -> ElementBuilder {
1046 self.root.set_attr(name, value);
1047 self
1048 }
1049
1050 /// Appends anything implementing `Into<Node>` into the tree.
1051 pub fn append<T: Into<Node>>(mut self, node: T) -> ElementBuilder {
1052 self.root.append_node(node.into());
1053 self
1054 }
1055
1056 /// Appends an iterator of things implementing `Into<Node>` into the tree.
1057 pub fn append_all<T: Into<Node>, I: IntoIterator<Item = T>>(mut self, iter: I) -> ElementBuilder {
1058 for node in iter {
1059 self.root.append_node(node.into());
1060 }
1061 self
1062 }
1063
1064 /// Builds the `Element`.
1065 pub fn build(self) -> Element {
1066 let mut element = self.root;
1067 // Set namespaces
1068 element.namespaces = Rc::new(NamespaceSet::from(self.namespaces));
1069 // Propagate namespaces
1070 for node in &element.children {
1071 if let Node::Element(ref e) = *node {
1072 e.namespaces.set_parent(Rc::clone(&element.namespaces));
1073 }
1074 }
1075 element
1076 }
1077}
1078
1079#[cfg(test)]
1080mod tests {
1081 use super::*;
1082
1083 #[test]
1084 fn test_element_new() {
1085 use std::iter::FromIterator;
1086
1087 let elem = Element::new( "name".to_owned()
1088 , None
1089 , Some("namespace".to_owned())
1090 , BTreeMap::from_iter(vec![ ("name".to_string(), "value".to_string()) ].into_iter() )
1091 , Vec::new() );
1092
1093 assert_eq!(elem.name(), "name");
1094 assert_eq!(elem.ns(), Some("namespace".to_owned()));
1095 assert_eq!(elem.attr("name"), Some("value"));
1096 assert_eq!(elem.attr("inexistent"), None);
1097 }
1098
1099 #[test]
1100 fn test_from_reader_simple() {
1101 let xml = "<foo></foo>";
1102 let mut reader = EventReader::from_str(xml);
1103 let elem = Element::from_reader(&mut reader);
1104
1105 let elem2 = Element::builder("foo").build();
1106
1107 assert_eq!(elem.unwrap(), elem2);
1108 }
1109
1110 #[test]
1111 fn test_from_reader_nested() {
1112 let xml = "<foo><bar baz='qxx' /></foo>";
1113 let mut reader = EventReader::from_str(xml);
1114 let elem = Element::from_reader(&mut reader);
1115
1116 let nested = Element::builder("bar")
1117 .attr("baz", "qxx")
1118 .build();
1119 let elem2 = Element::builder("foo")
1120 .append(nested)
1121 .build();
1122
1123 assert_eq!(elem.unwrap(), elem2);
1124 }
1125
1126 #[test]
1127 fn test_from_reader_with_prefix() {
1128 let xml = "<foo><prefix:bar baz='qxx' /></foo>";
1129 let mut reader = EventReader::from_str(xml);
1130 let elem = Element::from_reader(&mut reader);
1131
1132 let nested = Element::builder("prefix:bar")
1133 .attr("baz", "qxx")
1134 .build();
1135 let elem2 = Element::builder("foo")
1136 .append(nested)
1137 .build();
1138
1139 assert_eq!(elem.unwrap(), elem2);
1140 }
1141
1142 #[test]
1143 fn parses_spectest_xml() { // From: https://gitlab.com/lumi/minidom-rs/issues/8
1144 let xml = r#"
1145 <rng:grammar xmlns:rng="http://relaxng.org/ns/structure/1.0">
1146 <rng:name xmlns:rng="http://relaxng.org/ns/structure/1.0"></rng:name>
1147 </rng:grammar>
1148 "#;
1149 let mut reader = EventReader::from_str(xml);
1150 let _ = Element::from_reader(&mut reader).unwrap();
1151 }
1152
1153 #[test]
1154 fn does_not_unescape_cdata() {
1155 let xml = "<test><![CDATA['>blah<blah>]]></test>";
1156 let mut reader = EventReader::from_str(xml);
1157 let elem = Element::from_reader(&mut reader).unwrap();
1158 assert_eq!(elem.text(), "'>blah<blah>");
1159 }
1160}