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