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