Skip to main content

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