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