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