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: RxmlNamespace<'static>,
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: namespace.into(),
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().into()
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    /// Parse a document from a `io::BufRead`.
343    pub fn from_reader<R: io::BufRead>(reader: R) -> Result<Element> {
344        let mut tree_builder = TreeBuilder::new();
345        let mut driver = RawReader::new(reader);
346        while let Some(event) = driver.read()? {
347            tree_builder.process_event(event)?;
348
349            if let Some(root) = tree_builder.root.take() {
350                return Ok(root);
351            }
352        }
353        Err(Error::EndOfDocument)
354    }
355
356    /// Parse a document from a `io::BufRead`, allowing Prefixes to be specified. Useful to provide
357    /// knowledge of namespaces that would have been declared on parent elements not present in the
358    /// reader.
359    pub fn from_reader_with_prefixes<R: io::BufRead, P: Into<Prefixes>>(
360        reader: R,
361        prefixes: P,
362    ) -> Result<Element> {
363        let mut tree_builder = TreeBuilder::new().with_prefixes_stack([prefixes.into()].into());
364        let mut driver = RawReader::new(reader);
365        while let Some(event) = driver.read()? {
366            tree_builder.process_event(event)?;
367
368            if let Some(root) = tree_builder.root.take() {
369                return Ok(root);
370            }
371        }
372        Err(Error::EndOfDocument)
373    }
374
375    /// Output a document to a `io::Writer`.
376    pub fn write_to<W: io::Write>(&self, writer: &mut W) -> Result<()> {
377        self.to_writer(&mut ItemWriter::new(writer))
378    }
379
380    /// Output a document to a `io::Writer`.
381    pub fn write_to_decl<W: io::Write>(&self, writer: &mut W) -> Result<()> {
382        self.to_writer_decl(&mut ItemWriter::new(writer))
383    }
384
385    /// Output the document to an `ItemWriter`
386    pub fn to_writer<W: io::Write>(&self, writer: &mut ItemWriter<W>) -> Result<()> {
387        self.write_to_inner(writer)
388    }
389
390    /// Output the document to an `ItemWriter`
391    pub fn to_writer_decl<W: io::Write>(&self, writer: &mut ItemWriter<W>) -> Result<()> {
392        writer
393            .write(Item::XmlDeclaration(XmlVersion::V1_0))
394            .unwrap(); // TODO: error return
395        self.write_to_inner(writer)
396    }
397
398    /// Like `write_to()` but without the `<?xml?>` prelude
399    pub fn write_to_inner<W: io::Write>(&self, writer: &mut ItemWriter<W>) -> Result<()> {
400        for (prefix, namespace) in self.prefixes.declared_prefixes() {
401            assert!(writer.encoder.ns_tracker_mut().declare_fixed(
402                prefix.as_deref().map(TryInto::try_into).transpose()?,
403                namespace.clone().into(),
404            ));
405        }
406
407        writer.write(Item::ElementHeadStart(
408            self.namespace.clone(),
409            (*self.name).try_into()?,
410        ))?;
411
412        for (key, value) in &self.attributes {
413            let (prefix, name) = <&rxml::NameStr>::try_from(&**key)
414                .unwrap()
415                .split_name()
416                .unwrap();
417            let namespace = match prefix {
418                Some(prefix) => match writer.encoder.ns_tracker().lookup_prefix(Some(prefix)) {
419                    Ok(v) => v.into_static().clone(),
420                    Err(rxml::writer::PrefixError::Undeclared) => return Err(Error::InvalidPrefix),
421                },
422                None => RxmlNamespace::NONE,
423            };
424            writer.write(Item::Attribute(namespace, name, value))?;
425        }
426
427        if !self.children.is_empty() {
428            writer.write(Item::ElementHeadEnd)?;
429            for child in &self.children {
430                child.write_to_inner(writer)?;
431            }
432        }
433        writer.write(Item::ElementFoot)?;
434
435        Ok(())
436    }
437
438    /// Extracts all children into a collection.
439    pub fn take_nodes(&mut self) -> Vec<Node> {
440        self.children.drain(..).collect()
441    }
442
443    /// Returns an iterator over references to every child node of this element.
444    ///
445    /// # Examples
446    ///
447    /// ```rust
448    /// use minidom::Element;
449    ///
450    /// let elem: Element = "<root xmlns=\"ns1\">a<c1 />b<c2 />c</root>".parse().unwrap();
451    ///
452    /// let mut iter = elem.nodes();
453    ///
454    /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "a");
455    /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c1");
456    /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "b");
457    /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c2");
458    /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "c");
459    /// assert_eq!(iter.next(), None);
460    /// ```
461    #[inline]
462    pub fn nodes(&self) -> Nodes<'_> {
463        self.children.iter()
464    }
465
466    /// Returns an iterator over mutable references to every child node of this element.
467    #[inline]
468    pub fn nodes_mut(&mut self) -> NodesMut<'_> {
469        self.children.iter_mut()
470    }
471
472    /// Returns an iterator over references to every child element of this element.
473    ///
474    /// # Examples
475    ///
476    /// ```rust
477    /// use minidom::Element;
478    ///
479    /// let elem: Element = "<root xmlns=\"ns1\">hello<child1 xmlns=\"ns1\"/>this<child2 xmlns=\"ns1\"/>is<child3 xmlns=\"ns1\"/>ignored</root>".parse().unwrap();
480    ///
481    /// let mut iter = elem.children();
482    /// assert_eq!(iter.next().unwrap().name(), "child1");
483    /// assert_eq!(iter.next().unwrap().name(), "child2");
484    /// assert_eq!(iter.next().unwrap().name(), "child3");
485    /// assert_eq!(iter.next(), None);
486    /// ```
487    #[inline]
488    #[must_use]
489    pub fn children(&self) -> Children<'_> {
490        Children {
491            iter: self.children.iter(),
492        }
493    }
494
495    /// Returns an iterator over mutable references to every child element of this element.
496    #[inline]
497    #[must_use]
498    pub fn children_mut(&mut self) -> ChildrenMut<'_> {
499        ChildrenMut {
500            iter: self.children.iter_mut(),
501        }
502    }
503
504    /// Returns an iterator over the child Elements, draining the element of
505    /// all its child nodes **including text!**
506    ///
507    /// This is a bit of a footgun, so we make this hidden in the docs (it
508    /// needs to be pub for macro use). Once `extract_if`
509    /// ([rust#43244](https://github.com/rust-lang/rust/issues/43244))
510    /// is stabilized, we can replace this with a take_children which doesn't
511    /// remove text nodes.
512    #[inline]
513    #[doc(hidden)]
514    pub fn take_contents_as_children(&mut self) -> ContentsAsChildren<'_> {
515        ContentsAsChildren {
516            iter: self.children.drain(..),
517        }
518    }
519
520    /// Returns an iterator over references to every text node of this element.
521    ///
522    /// # Examples
523    ///
524    /// ```rust
525    /// use minidom::Element;
526    ///
527    /// let elem: Element = "<root xmlns=\"ns1\">hello<c /> world!</root>".parse().unwrap();
528    ///
529    /// let mut iter = elem.texts();
530    /// assert_eq!(iter.next().unwrap(), "hello");
531    /// assert_eq!(iter.next().unwrap(), " world!");
532    /// assert_eq!(iter.next(), None);
533    /// ```
534    #[inline]
535    #[must_use]
536    pub fn texts(&self) -> Texts<'_> {
537        Texts {
538            iter: self.children.iter(),
539        }
540    }
541
542    /// Returns an iterator over mutable references to every text node of this element.
543    #[inline]
544    #[must_use]
545    pub fn texts_mut(&mut self) -> TextsMut<'_> {
546        TextsMut {
547            iter: self.children.iter_mut(),
548        }
549    }
550
551    /// Appends a child node to the `Element`, returning the appended node.
552    ///
553    /// # Examples
554    ///
555    /// ```rust
556    /// use minidom::Element;
557    ///
558    /// let mut elem = Element::bare("root", "ns1");
559    ///
560    /// assert_eq!(elem.children().count(), 0);
561    ///
562    /// elem.append_child(Element::bare("child", "ns1"));
563    ///
564    /// {
565    ///     let mut iter = elem.children();
566    ///     assert_eq!(iter.next().unwrap().name(), "child");
567    ///     assert_eq!(iter.next(), None);
568    /// }
569    ///
570    /// let child = elem.append_child(Element::bare("new", "ns1"));
571    ///
572    /// assert_eq!(child.name(), "new");
573    /// ```
574    pub fn append_child(&mut self, child: Element) -> &mut Element {
575        self.children.push(Node::Element(child));
576        if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
577            cld
578        } else {
579            unreachable!()
580        }
581    }
582
583    /// Appends a text node to an `Element`.
584    ///
585    /// # Examples
586    ///
587    /// ```rust
588    /// use minidom::Element;
589    ///
590    /// let mut elem = Element::bare("node", "ns1");
591    ///
592    /// assert_eq!(elem.text(), "");
593    ///
594    /// elem.append_text_node("text");
595    ///
596    /// assert_eq!(elem.text(), "text");
597    /// ```
598    pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
599        self.children.push(Node::Text(child.into()));
600    }
601
602    /// Appends a string as plain text to an `Element`.
603    ///
604    /// If the last child node of the element is a text node, the string will be appended to it.
605    /// Otherwise, a new text node will be created.
606    ///
607    /// # Examples
608    ///
609    /// ```rust
610    /// use minidom::Element;
611    ///
612    /// let mut elem = Element::bare("node", "ns1");
613    ///
614    /// assert_eq!(elem.text(), "");
615    ///
616    /// elem.append_text_node("text");
617    ///
618    /// elem.append_text(" and more text");
619    ///
620    /// assert_eq!(elem.nodes().count(), 1);
621    /// ```
622    pub fn append_text<S: Into<String>>(&mut self, text: S) {
623        if let Some(Node::Text(ref mut child)) = self.children.last_mut() {
624            child.push_str(&text.into());
625        } else {
626            self.append_text_node(text);
627        }
628    }
629
630    /// Appends a node to an `Element`.
631    ///
632    /// # Examples
633    ///
634    /// ```rust
635    /// use minidom::{Element, Node};
636    ///
637    /// let mut elem = Element::bare("node", "ns1");
638    ///
639    /// elem.append_node(Node::Text("hello".to_owned()));
640    ///
641    /// assert_eq!(elem.text(), "hello");
642    /// ```
643    pub fn append_node(&mut self, node: Node) {
644        self.children.push(node);
645    }
646
647    /// Returns the concatenation of all text nodes in the `Element`.
648    ///
649    /// # Examples
650    ///
651    /// ```rust
652    /// use minidom::Element;
653    ///
654    /// let elem: Element = "<node xmlns=\"ns1\">hello,<split /> world!</node>".parse().unwrap();
655    ///
656    /// assert_eq!(elem.text(), "hello, world!");
657    /// ```
658    #[must_use]
659    pub fn text(&self) -> String {
660        self.texts().fold(String::new(), |ret, new| ret + new)
661    }
662
663    /// Returns a reference to the first child element with the specific name and namespace, if it
664    /// exists in the direct descendants of this `Element`, else returns `None`.
665    ///
666    /// # Examples
667    ///
668    /// ```rust
669    /// use minidom::{Element, NSChoice};
670    ///
671    /// let elem: Element = r#"<node xmlns="ns"><a/><a xmlns="other_ns" /><b/></node>"#.parse().unwrap();
672    /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
673    /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
674    /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
675    /// assert_eq!(elem.get_child("c", "ns"), None);
676    /// assert_eq!(elem.get_child("b", "other_ns"), None);
677    /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
678    /// ```
679    pub fn get_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
680        &self,
681        name: N,
682        namespace: NS,
683    ) -> Option<&Element> {
684        let namespace = namespace.into();
685        for fork in &self.children {
686            if let Node::Element(ref e) = *fork {
687                if e.is(name.as_ref(), namespace) {
688                    return Some(e);
689                }
690            }
691        }
692        None
693    }
694
695    /// Returns a mutable reference to the first child element with the specific name and namespace,
696    /// if it exists in the direct descendants of this `Element`, else returns `None`.
697    pub fn get_child_mut<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
698        &mut self,
699        name: N,
700        namespace: NS,
701    ) -> Option<&mut Element> {
702        let namespace = namespace.into();
703        for fork in &mut self.children {
704            if let Node::Element(ref mut e) = *fork {
705                if e.is(name.as_ref(), namespace) {
706                    return Some(e);
707                }
708            }
709        }
710        None
711    }
712
713    /// Returns whether a specific child with this name and namespace exists in the direct
714    /// descendants of the `Element`.
715    ///
716    /// # Examples
717    ///
718    /// ```rust
719    /// use minidom::{Element, NSChoice};
720    ///
721    /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
722    /// assert_eq!(elem.has_child("a", "other_ns"), true);
723    /// assert_eq!(elem.has_child("a", "ns"), true);
724    /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
725    /// assert_eq!(elem.has_child("b", "ns"), true);
726    /// assert_eq!(elem.has_child("b", "other_ns"), false);
727    /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
728    /// ```
729    pub fn has_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
730        &self,
731        name: N,
732        namespace: NS,
733    ) -> bool {
734        self.get_child(name, namespace).is_some()
735    }
736
737    /// Removes the first child with this name and namespace, if it exists, and returns an
738    /// `Option<Element>` containing this child if it succeeds.
739    /// Returns `None` if no child matches this name and namespace.
740    ///
741    /// # Examples
742    ///
743    /// ```rust
744    /// use minidom::{Element, NSChoice};
745    ///
746    /// let mut elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
747    /// assert!(elem.remove_child("a", "ns").unwrap().is("a", "ns"));
748    /// assert!(elem.remove_child("a", "ns").is_none());
749    /// assert!(elem.remove_child("inexistent", "inexistent").is_none());
750    /// ```
751    pub fn remove_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
752        &mut self,
753        name: N,
754        namespace: NS,
755    ) -> Option<Element> {
756        let name = name.as_ref();
757        let namespace = namespace.into();
758        let idx = self.children.iter().position(|x| {
759            if let Node::Element(ref elm) = x {
760                elm.is(name, namespace)
761            } else {
762                false
763            }
764        })?;
765        self.children.remove(idx).into_element()
766    }
767
768    /// Remove the leading nodes up to the first child element and
769    /// return it
770    pub fn unshift_child(&mut self) -> Option<Element> {
771        while !self.children.is_empty() {
772            if let Some(el) = self.children.remove(0).into_element() {
773                return Some(el);
774            }
775        }
776
777        None
778    }
779}
780
781/// An iterator over references to child elements of an `Element`.
782pub struct Children<'a> {
783    iter: slice::Iter<'a, Node>,
784}
785
786impl<'a> Iterator for Children<'a> {
787    type Item = &'a Element;
788
789    fn next(&mut self) -> Option<&'a Element> {
790        for item in &mut self.iter {
791            if let Node::Element(ref child) = *item {
792                return Some(child);
793            }
794        }
795        None
796    }
797}
798
799/// An iterator over mutable references to child elements of an `Element`.
800pub struct ChildrenMut<'a> {
801    iter: slice::IterMut<'a, Node>,
802}
803
804impl<'a> Iterator for ChildrenMut<'a> {
805    type Item = &'a mut Element;
806
807    fn next(&mut self) -> Option<&'a mut Element> {
808        for item in &mut self.iter {
809            if let Node::Element(ref mut child) = *item {
810                return Some(child);
811            }
812        }
813        None
814    }
815}
816
817/// An iterator over references to child elements of an `Element`.
818pub struct ContentsAsChildren<'a> {
819    iter: alloc::vec::Drain<'a, Node>,
820}
821
822impl Iterator for ContentsAsChildren<'_> {
823    type Item = Element;
824
825    fn next(&mut self) -> Option<Element> {
826        for item in &mut self.iter {
827            if let Node::Element(child) = item {
828                return Some(child);
829            }
830        }
831        None
832    }
833}
834
835/// An iterator over references to child text nodes of an `Element`.
836pub struct Texts<'a> {
837    iter: slice::Iter<'a, Node>,
838}
839
840impl<'a> Iterator for Texts<'a> {
841    type Item = &'a str;
842
843    fn next(&mut self) -> Option<&'a str> {
844        for item in &mut self.iter {
845            if let Node::Text(ref child) = *item {
846                return Some(child);
847            }
848        }
849        None
850    }
851}
852
853/// An iterator over mutable references to child text nodes of an `Element`.
854pub struct TextsMut<'a> {
855    iter: slice::IterMut<'a, Node>,
856}
857
858impl<'a> Iterator for TextsMut<'a> {
859    type Item = &'a mut String;
860
861    fn next(&mut self) -> Option<&'a mut String> {
862        for item in &mut self.iter {
863            if let Node::Text(ref mut child) = *item {
864                return Some(child);
865            }
866        }
867        None
868    }
869}
870
871/// An iterator over references to all child nodes of an `Element`.
872pub type Nodes<'a> = slice::Iter<'a, Node>;
873
874/// An iterator over mutable references to all child nodes of an `Element`.
875pub type NodesMut<'a> = slice::IterMut<'a, Node>;
876
877/// An iterator over the attributes of an `Element`.
878pub struct Attrs<'a> {
879    iter: btree_map::Iter<'a, String, String>,
880}
881
882impl<'a> Iterator for Attrs<'a> {
883    type Item = (&'a str, &'a str);
884
885    fn next(&mut self) -> Option<Self::Item> {
886        self.iter.next().map(|(x, y)| (x.as_ref(), y.as_ref()))
887    }
888}
889
890/// An iterator over the attributes of an `Element`, with the values mutable.
891pub struct AttrsMut<'a> {
892    iter: btree_map::IterMut<'a, String, String>,
893}
894
895impl<'a> Iterator for AttrsMut<'a> {
896    type Item = (&'a str, &'a mut String);
897
898    fn next(&mut self) -> Option<Self::Item> {
899        self.iter.next().map(|(x, y)| (x.as_ref(), y))
900    }
901}
902
903/// A builder for `Element`s.
904pub struct ElementBuilder {
905    root: Element,
906}
907
908impl ElementBuilder {
909    /// Sets a custom prefix. It is not possible to set the same prefix twice.
910    pub fn prefix<S: Into<Namespace>>(
911        mut self,
912        prefix: Prefix,
913        namespace: S,
914    ) -> Result<ElementBuilder> {
915        if self.root.prefixes.get(&prefix).is_some() {
916            return Err(Error::DuplicatePrefix);
917        }
918        self.root.prefixes.insert(prefix, namespace.into());
919        Ok(self)
920    }
921
922    /// Sets an attribute.
923    #[must_use]
924    pub fn attr<S: Into<String>, V: IntoAttributeValue>(
925        mut self,
926        name: S,
927        value: V,
928    ) -> ElementBuilder {
929        self.root.set_attr(name, value);
930        self
931    }
932
933    /// Appends anything implementing `Into<Node>` into the tree.
934    #[must_use]
935    pub fn append<T: Into<Node>>(mut self, node: T) -> ElementBuilder {
936        self.root.append_node(node.into());
937        self
938    }
939
940    /// Appends an iterator of things implementing `Into<Node>` into the tree.
941    #[must_use]
942    pub fn append_all<T: Into<Node>, I: IntoIterator<Item = T>>(
943        mut self,
944        iter: I,
945    ) -> ElementBuilder {
946        for node in iter {
947            self.root.append_node(node.into());
948        }
949        self
950    }
951
952    /// Builds the `Element`.
953    #[must_use]
954    pub fn build(self) -> Element {
955        self.root
956    }
957}
958
959#[cfg(test)]
960mod tests {
961    use super::*;
962
963    #[test]
964    fn test_element_new() {
965        let elem = Element::new(
966            "name".to_owned(),
967            "namespace".to_owned(),
968            (None, "namespace".to_owned()),
969            BTreeMap::from_iter([("name".to_string(), "value".to_string())].into_iter()),
970            Vec::new(),
971        );
972
973        assert_eq!(elem.name(), "name");
974        assert_eq!(elem.ns(), "namespace".to_owned());
975        assert_eq!(elem.attr("name"), Some("value"));
976        assert_eq!(elem.attr("inexistent"), None);
977    }
978
979    #[test]
980    fn test_from_reader_simple() {
981        let xml = b"<foo xmlns='ns1'></foo>";
982        let elem = Element::from_reader(&xml[..]);
983
984        let elem2 = Element::builder("foo", "ns1").build();
985
986        assert_eq!(elem.unwrap(), elem2);
987    }
988
989    #[test]
990    fn test_from_reader_nested() {
991        let xml = b"<foo xmlns='ns1'><bar xmlns='ns1' baz='qxx' /></foo>";
992        let elem = Element::from_reader(&xml[..]);
993
994        let nested = Element::builder("bar", "ns1").attr("baz", "qxx").build();
995        let elem2 = Element::builder("foo", "ns1").append(nested).build();
996
997        assert_eq!(elem.unwrap(), elem2);
998    }
999
1000    #[test]
1001    fn test_from_reader_with_prefix() {
1002        let xml = b"<foo xmlns='ns1'><prefix:bar xmlns:prefix='ns1' baz='qxx' /></foo>";
1003        let elem = Element::from_reader(&xml[..]);
1004
1005        let nested = Element::builder("bar", "ns1").attr("baz", "qxx").build();
1006        let elem2 = Element::builder("foo", "ns1").append(nested).build();
1007
1008        assert_eq!(elem.unwrap(), elem2);
1009    }
1010
1011    #[test]
1012    fn test_from_reader_split_prefix() {
1013        let xml = b"<foo:bar xmlns:foo='ns1'/>";
1014        let elem = Element::from_reader(&xml[..]).unwrap();
1015
1016        assert_eq!(elem.name(), String::from("bar"));
1017        assert_eq!(elem.ns(), String::from("ns1"));
1018        // Ensure the prefix is properly added to the store
1019        assert_eq!(
1020            elem.prefixes.get(&Some(String::from("foo"))),
1021            Some(&String::from("ns1"))
1022        );
1023    }
1024
1025    #[test]
1026    fn parses_spectest_xml() {
1027        // From: https://gitlab.com/lumi/minidom-rs/issues/8
1028        let xml = br#"<rng:grammar xmlns:rng="http://relaxng.org/ns/structure/1.0">
1029                <rng:name xmlns:rng="http://relaxng.org/ns/structure/1.0"></rng:name>
1030            </rng:grammar>
1031        "#;
1032        let _ = Element::from_reader(&xml[..]).unwrap();
1033    }
1034
1035    #[test]
1036    fn does_not_unescape_cdata() {
1037        let xml = b"<test xmlns='test'><![CDATA[&apos;&gt;blah<blah>]]></test>";
1038        let elem = Element::from_reader(&xml[..]).unwrap();
1039        assert_eq!(elem.text(), "&apos;&gt;blah<blah>");
1040    }
1041
1042    #[test]
1043    fn test_compare_all_ns() {
1044        let xml = b"<foo xmlns='foo' xmlns:bar='baz'><bar:meh xmlns:bar='baz' /></foo>";
1045        let elem = Element::from_reader(&xml[..]).unwrap();
1046
1047        let elem2 = elem.clone();
1048
1049        let xml3 = b"<foo xmlns='foo'><bar:meh xmlns:bar='baz'/></foo>";
1050        let elem3 = Element::from_reader(&xml3[..]).unwrap();
1051
1052        let xml4 = b"<prefix:foo xmlns:prefix='foo'><bar:meh xmlns:bar='baz'/></prefix:foo>";
1053        let elem4 = Element::from_reader(&xml4[..]).unwrap();
1054
1055        assert_eq!(elem, elem2);
1056        assert_eq!(elem, elem3);
1057        assert_eq!(elem, elem4);
1058    }
1059
1060    #[test]
1061    fn test_compare_empty_children() {
1062        let elem1 = Element::bare("p", "");
1063        let elem2 = Element::builder("p", "")
1064            .append(Node::Element(Element::bare("span", "")))
1065            .build();
1066
1067        assert_ne!(elem1, elem2);
1068    }
1069
1070    #[test]
1071    fn test_from_reader_with_prefixes() {
1072        let xml = b"<foo><bar xmlns='baz'/></foo>";
1073        let elem =
1074            Element::from_reader_with_prefixes(&xml[..], String::from("jabber:client")).unwrap();
1075
1076        let xml2 = b"<foo xmlns='jabber:client'><bar xmlns='baz'/></foo>";
1077        let elem2 = Element::from_reader(&xml2[..]).unwrap();
1078
1079        assert_eq!(elem, elem2);
1080    }
1081
1082    #[test]
1083    fn test_from_reader_with_prefixes_serialization() {
1084        let prefixes: BTreeMap<Option<String>, String> = {
1085            let mut tmp = BTreeMap::new();
1086            tmp.insert(None, String::from("foo"));
1087            tmp.insert(Some(String::from("test")), String::from("bar"));
1088            tmp
1089        };
1090
1091        let input = r#"<foo test:attr="true"><bar/></foo>"#;
1092        let output = r#"<foo xmlns='foo' xmlns:test='bar' test:attr='true'><bar/></foo>"#;
1093
1094        let elem = Element::from_reader_with_prefixes(input.as_ref(), prefixes).unwrap();
1095        assert_eq!(String::from(&elem), output);
1096    }
1097
1098    #[test]
1099    fn failure_with_duplicate_namespace() {
1100        let _: Element = r###"<?xml version="1.0" encoding="UTF-8"?>
1101            <wsdl:definitions
1102                    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
1103                    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
1104                <wsdl:types>
1105                    <xsd:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
1106                    </xsd:schema>
1107                </wsdl:types>
1108            </wsdl:definitions>
1109        "###
1110        .parse()
1111        .unwrap();
1112    }
1113}