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