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