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