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