minidom/
element.rs

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