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}