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::convert::{TryFrom, TryInto};
  24use std::io::{BufRead, Write};
  25use std::sync::Arc;
  26
  27use std::borrow::Cow;
  28use std::str;
  29
  30use rxml::writer::{Encoder, Item, TrackNamespace};
  31use rxml::{EventRead, Lexer, PullDriver, RawParser, XmlVersion};
  32
  33use std::str::FromStr;
  34
  35use std::slice;
  36
  37fn encode_and_write<W: Write, T: rxml::writer::TrackNamespace>(
  38    item: Item<'_>,
  39    enc: &mut Encoder<T>,
  40    mut w: W,
  41) -> rxml::Result<()> {
  42    let mut buf = rxml::bytes::BytesMut::new();
  43    enc.encode_into_bytes(item, &mut buf)
  44        .expect("encoder driven incorrectly");
  45    w.write_all(&buf[..])?;
  46    Ok(())
  47}
  48
  49/// Wrapper around a [`std::io::Write`] and an [`rxml::writer::Encoder`], to
  50/// provide a simple function to write an rxml Item to a writer.
  51pub struct CustomItemWriter<W, T> {
  52    writer: W,
  53    encoder: Encoder<T>,
  54}
  55
  56impl<W: Write> CustomItemWriter<W, rxml::writer::SimpleNamespaces> {
  57    pub(crate) fn new(writer: W) -> Self {
  58        Self {
  59            writer,
  60            encoder: Encoder::new(),
  61        }
  62    }
  63}
  64
  65impl<W: Write, T: rxml::writer::TrackNamespace> CustomItemWriter<W, T> {
  66    pub(crate) fn write(&mut self, item: Item<'_>) -> rxml::Result<()> {
  67        encode_and_write(item, &mut self.encoder, &mut self.writer)
  68    }
  69}
  70
  71/// Type alias to simplify the use for the default namespace tracking
  72/// implementation.
  73pub type ItemWriter<W> = CustomItemWriter<W, rxml::writer::SimpleNamespaces>;
  74
  75/// helper function to escape a `&[u8]` and replace all
  76/// xml special characters (<, >, &, ', ") with their corresponding
  77/// xml escaped value.
  78pub fn escape(raw: &[u8]) -> Cow<[u8]> {
  79    let mut escapes: Vec<(usize, &'static [u8])> = Vec::new();
  80    let mut bytes = raw.iter();
  81    fn to_escape(b: u8) -> bool {
  82        matches!(b, b'<' | b'>' | b'\'' | b'&' | b'"')
  83    }
  84
  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: BTreeMap<String, String>,
 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            self.nodes()
 150                .zip(other.nodes())
 151                .all(|(node1, node2)| node1 == node2)
 152        } else {
 153            false
 154        }
 155    }
 156}
 157
 158impl Element {
 159    pub(crate) fn new<P: Into<Prefixes>>(
 160        name: String,
 161        namespace: String,
 162        prefixes: P,
 163        attributes: BTreeMap<String, String>,
 164        children: Vec<Node>,
 165    ) -> Element {
 166        Element {
 167            name,
 168            namespace,
 169            prefixes: prefixes.into(),
 170            attributes,
 171            children,
 172        }
 173    }
 174
 175    /// Return a builder for an `Element` with the given `name`.
 176    ///
 177    /// # Examples
 178    ///
 179    /// ```rust
 180    /// use minidom::Element;
 181    ///
 182    /// let elem = Element::builder("name", "namespace")
 183    ///                    .attr("name", "value")
 184    ///                    .append("inner")
 185    ///                    .build();
 186    ///
 187    /// assert_eq!(elem.name(), "name");
 188    /// assert_eq!(elem.ns(), "namespace".to_owned());
 189    /// assert_eq!(elem.attr("name"), Some("value"));
 190    /// assert_eq!(elem.attr("inexistent"), None);
 191    /// assert_eq!(elem.text(), "inner");
 192    /// ```
 193    pub fn builder<S: AsRef<str>, NS: Into<String>>(name: S, namespace: NS) -> ElementBuilder {
 194        ElementBuilder {
 195            root: Element::new(
 196                name.as_ref().to_string(),
 197                namespace.into(),
 198                None,
 199                BTreeMap::new(),
 200                Vec::new(),
 201            ),
 202        }
 203    }
 204
 205    /// Returns a bare minimum `Element` with this name.
 206    ///
 207    /// # Examples
 208    ///
 209    /// ```rust
 210    /// use minidom::Element;
 211    ///
 212    /// let bare = Element::bare("name", "namespace");
 213    ///
 214    /// assert_eq!(bare.name(), "name");
 215    /// assert_eq!(bare.ns(), "namespace");
 216    /// assert_eq!(bare.attr("name"), None);
 217    /// assert_eq!(bare.text(), "");
 218    /// ```
 219    pub fn bare<S: Into<String>, NS: Into<String>>(name: S, namespace: NS) -> Element {
 220        Element::new(
 221            name.into(),
 222            namespace.into(),
 223            None,
 224            BTreeMap::new(),
 225            Vec::new(),
 226        )
 227    }
 228
 229    /// Returns a reference to the local name of this element (that is, without a possible prefix).
 230    pub fn name(&self) -> &str {
 231        &self.name
 232    }
 233
 234    /// Returns a reference to the namespace of this element.
 235    pub fn ns(&self) -> String {
 236        self.namespace.clone()
 237    }
 238
 239    /// Returns a reference to the value of the given attribute, if it exists, else `None`.
 240    pub fn attr(&self, name: &str) -> Option<&str> {
 241        if let Some(value) = self.attributes.get(name) {
 242            return Some(value);
 243        }
 244        None
 245    }
 246
 247    /// Returns an iterator over the attributes of this element.
 248    ///
 249    /// # Example
 250    ///
 251    /// ```rust
 252    /// use minidom::Element;
 253    ///
 254    /// let elm: Element = "<elem xmlns=\"ns1\" a=\"b\" />".parse().unwrap();
 255    ///
 256    /// let mut iter = elm.attrs();
 257    ///
 258    /// assert_eq!(iter.next().unwrap(), ("a", "b"));
 259    /// assert_eq!(iter.next(), None);
 260    /// ```
 261    pub fn attrs(&self) -> Attrs {
 262        Attrs {
 263            iter: self.attributes.iter(),
 264        }
 265    }
 266
 267    /// Returns an iterator over the attributes of this element, with the value being a mutable
 268    /// reference.
 269    pub fn attrs_mut(&mut self) -> AttrsMut {
 270        AttrsMut {
 271            iter: self.attributes.iter_mut(),
 272        }
 273    }
 274
 275    /// Modifies the value of an attribute.
 276    pub fn set_attr<S: Into<String>, V: IntoAttributeValue>(&mut self, name: S, val: V) {
 277        let name = name.into();
 278        let val = val.into_attribute_value();
 279
 280        if let Some(value) = self.attributes.get_mut(&name) {
 281            *value = val
 282                .expect("removing existing value via set_attr, this is not yet supported (TODO)"); // TODO
 283            return;
 284        }
 285
 286        if let Some(val) = val {
 287            self.attributes.insert(name, val);
 288        }
 289    }
 290
 291    /// Returns whether the element has the given name and namespace.
 292    ///
 293    /// # Examples
 294    ///
 295    /// ```rust
 296    /// use minidom::{Element, NSChoice};
 297    ///
 298    /// let elem = Element::builder("name", "namespace").build();
 299    ///
 300    /// assert_eq!(elem.is("name", "namespace"), true);
 301    /// assert_eq!(elem.is("name", "wrong"), false);
 302    /// assert_eq!(elem.is("wrong", "namespace"), false);
 303    /// assert_eq!(elem.is("wrong", "wrong"), false);
 304    ///
 305    /// assert_eq!(elem.is("name", NSChoice::OneOf("namespace")), true);
 306    /// assert_eq!(elem.is("name", NSChoice::OneOf("foo")), false);
 307    /// assert_eq!(elem.is("name", NSChoice::AnyOf(&["foo", "namespace"])), true);
 308    /// assert_eq!(elem.is("name", NSChoice::Any), true);
 309    /// ```
 310    pub fn is<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(&self, name: N, namespace: NS) -> bool {
 311        self.name == name.as_ref() && namespace.into().compare(self.namespace.as_ref())
 312    }
 313
 314    /// Returns whether the element has the given namespace.
 315    ///
 316    /// # Examples
 317    ///
 318    /// ```rust
 319    /// use minidom::{Element, NSChoice};
 320    ///
 321    /// let elem = Element::builder("name", "namespace").build();
 322    ///
 323    /// assert_eq!(elem.has_ns("namespace"), true);
 324    /// assert_eq!(elem.has_ns("wrong"), false);
 325    ///
 326    /// assert_eq!(elem.has_ns(NSChoice::OneOf("namespace")), true);
 327    /// assert_eq!(elem.has_ns(NSChoice::OneOf("foo")), false);
 328    /// assert_eq!(elem.has_ns(NSChoice::AnyOf(&["foo", "namespace"])), true);
 329    /// assert_eq!(elem.has_ns(NSChoice::Any), true);
 330    /// ```
 331    pub fn has_ns<'a, NS: Into<NSChoice<'a>>>(&self, namespace: NS) -> bool {
 332        namespace.into().compare(self.namespace.as_ref())
 333    }
 334
 335    /// Parse a document from a `BufRead`.
 336    pub fn from_reader<R: BufRead>(reader: R) -> Result<Element> {
 337        let mut tree_builder = TreeBuilder::new();
 338        let mut driver = PullDriver::wrap(reader, Lexer::new(), RawParser::new());
 339        while let Some(event) = driver.read()? {
 340            tree_builder.process_event(event)?;
 341
 342            if let Some(root) = tree_builder.root.take() {
 343                return Ok(root);
 344            }
 345        }
 346        Err(Error::EndOfDocument)
 347    }
 348
 349    /// Parse a document from a `BufRead`, allowing Prefixes to be specified. Useful to provide
 350    /// knowledge of namespaces that would have been declared on parent elements not present in the
 351    /// reader.
 352    pub fn from_reader_with_prefixes<R: BufRead, P: Into<Prefixes>>(
 353        reader: R,
 354        prefixes: P,
 355    ) -> Result<Element> {
 356        let mut tree_builder = TreeBuilder::new().with_prefixes_stack(vec![prefixes.into()]);
 357        let mut driver = PullDriver::wrap(reader, Lexer::new(), RawParser::new());
 358        while let Some(event) = driver.read()? {
 359            tree_builder.process_event(event)?;
 360
 361            if let Some(root) = tree_builder.root.take() {
 362                return Ok(root);
 363            }
 364        }
 365        Err(Error::EndOfDocument)
 366    }
 367
 368    /// Output a document to a `Writer`.
 369    pub fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
 370        self.to_writer(&mut ItemWriter::new(writer))
 371    }
 372
 373    /// Output a document to a `Writer`.
 374    pub fn write_to_decl<W: Write>(&self, writer: &mut W) -> Result<()> {
 375        self.to_writer_decl(&mut ItemWriter::new(writer))
 376    }
 377
 378    /// Output the document to an `ItemWriter`
 379    pub fn to_writer<W: Write>(&self, writer: &mut ItemWriter<W>) -> Result<()> {
 380        self.write_to_inner(writer)
 381    }
 382
 383    /// Output the document to an `ItemWriter`
 384    pub fn to_writer_decl<W: Write>(&self, writer: &mut ItemWriter<W>) -> Result<()> {
 385        writer
 386            .write(Item::XmlDeclaration(XmlVersion::V1_0))
 387            .unwrap(); // TODO: error return
 388        self.write_to_inner(writer)
 389    }
 390
 391    /// Like `write_to()` but without the `<?xml?>` prelude
 392    pub fn write_to_inner<W: Write>(&self, writer: &mut ItemWriter<W>) -> Result<()> {
 393        for (prefix, namespace) in self.prefixes.declared_prefixes() {
 394            assert!(writer.encoder.inner_mut().declare_fixed(
 395                prefix.as_ref().map(|x| (&**x).try_into()).transpose()?,
 396                Some(Arc::new(namespace.clone().try_into()?))
 397            ));
 398        }
 399
 400        let namespace = if self.namespace.len() == 0 {
 401            None
 402        } else {
 403            Some(Arc::new(self.namespace.clone().try_into()?))
 404        };
 405        writer.write(Item::ElementHeadStart(namespace, (*self.name).try_into()?))?;
 406
 407        for (key, value) in self.attributes.iter() {
 408            let (prefix, name) = <&rxml::NameStr>::try_from(&**key)
 409                .unwrap()
 410                .split_name()
 411                .unwrap();
 412            let namespace = match prefix {
 413                Some(prefix) => match writer.encoder.inner().lookup_prefix(Some(prefix)) {
 414                    Ok(v) => Some(v),
 415                    Err(rxml::writer::PrefixError::Undeclared) => return Err(Error::InvalidPrefix),
 416                },
 417                None => None,
 418            };
 419            writer.write(Item::Attribute(namespace, name, (&**value).try_into()?))?;
 420        }
 421
 422        if !self.children.is_empty() {
 423            writer.write(Item::ElementHeadEnd)?;
 424            for child in self.children.iter() {
 425                child.write_to_inner(writer)?;
 426            }
 427        }
 428        writer.write(Item::ElementFoot)?;
 429
 430        Ok(())
 431    }
 432
 433    /// Returns an iterator over references to every child node of this element.
 434    ///
 435    /// # Examples
 436    ///
 437    /// ```rust
 438    /// use minidom::Element;
 439    ///
 440    /// let elem: Element = "<root xmlns=\"ns1\">a<c1 />b<c2 />c</root>".parse().unwrap();
 441    ///
 442    /// let mut iter = elem.nodes();
 443    ///
 444    /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "a");
 445    /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c1");
 446    /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "b");
 447    /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c2");
 448    /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "c");
 449    /// assert_eq!(iter.next(), None);
 450    /// ```
 451    #[inline]
 452    pub fn nodes(&self) -> Nodes {
 453        self.children.iter()
 454    }
 455
 456    /// Returns an iterator over mutable references to every child node of this element.
 457    #[inline]
 458    pub fn nodes_mut(&mut self) -> NodesMut {
 459        self.children.iter_mut()
 460    }
 461
 462    /// Returns an iterator over references to every child element of this element.
 463    ///
 464    /// # Examples
 465    ///
 466    /// ```rust
 467    /// use minidom::Element;
 468    ///
 469    /// let elem: Element = "<root xmlns=\"ns1\">hello<child1 xmlns=\"ns1\"/>this<child2 xmlns=\"ns1\"/>is<child3 xmlns=\"ns1\"/>ignored</root>".parse().unwrap();
 470    ///
 471    /// let mut iter = elem.children();
 472    /// assert_eq!(iter.next().unwrap().name(), "child1");
 473    /// assert_eq!(iter.next().unwrap().name(), "child2");
 474    /// assert_eq!(iter.next().unwrap().name(), "child3");
 475    /// assert_eq!(iter.next(), None);
 476    /// ```
 477    #[inline]
 478    pub fn children(&self) -> Children {
 479        Children {
 480            iter: self.children.iter(),
 481        }
 482    }
 483
 484    /// Returns an iterator over mutable references to every child element of this element.
 485    #[inline]
 486    pub fn children_mut(&mut self) -> ChildrenMut {
 487        ChildrenMut {
 488            iter: self.children.iter_mut(),
 489        }
 490    }
 491
 492    /// Returns an iterator over references to every text node of this element.
 493    ///
 494    /// # Examples
 495    ///
 496    /// ```rust
 497    /// use minidom::Element;
 498    ///
 499    /// let elem: Element = "<root xmlns=\"ns1\">hello<c /> world!</root>".parse().unwrap();
 500    ///
 501    /// let mut iter = elem.texts();
 502    /// assert_eq!(iter.next().unwrap(), "hello");
 503    /// assert_eq!(iter.next().unwrap(), " world!");
 504    /// assert_eq!(iter.next(), None);
 505    /// ```
 506    #[inline]
 507    pub fn texts(&self) -> Texts {
 508        Texts {
 509            iter: self.children.iter(),
 510        }
 511    }
 512
 513    /// Returns an iterator over mutable references to every text node of this element.
 514    #[inline]
 515    pub fn texts_mut(&mut self) -> TextsMut {
 516        TextsMut {
 517            iter: self.children.iter_mut(),
 518        }
 519    }
 520
 521    /// Appends a child node to the `Element`, returning the appended node.
 522    ///
 523    /// # Examples
 524    ///
 525    /// ```rust
 526    /// use minidom::Element;
 527    ///
 528    /// let mut elem = Element::bare("root", "ns1");
 529    ///
 530    /// assert_eq!(elem.children().count(), 0);
 531    ///
 532    /// elem.append_child(Element::bare("child", "ns1"));
 533    ///
 534    /// {
 535    ///     let mut iter = elem.children();
 536    ///     assert_eq!(iter.next().unwrap().name(), "child");
 537    ///     assert_eq!(iter.next(), None);
 538    /// }
 539    ///
 540    /// let child = elem.append_child(Element::bare("new", "ns1"));
 541    ///
 542    /// assert_eq!(child.name(), "new");
 543    /// ```
 544    pub fn append_child(&mut self, child: Element) -> &mut Element {
 545        self.children.push(Node::Element(child));
 546        if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
 547            cld
 548        } else {
 549            unreachable!()
 550        }
 551    }
 552
 553    /// Appends a text node to an `Element`.
 554    ///
 555    /// # Examples
 556    ///
 557    /// ```rust
 558    /// use minidom::Element;
 559    ///
 560    /// let mut elem = Element::bare("node", "ns1");
 561    ///
 562    /// assert_eq!(elem.text(), "");
 563    ///
 564    /// elem.append_text_node("text");
 565    ///
 566    /// assert_eq!(elem.text(), "text");
 567    /// ```
 568    pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
 569        self.children.push(Node::Text(child.into()));
 570    }
 571
 572    /// Appends a node to an `Element`.
 573    ///
 574    /// # Examples
 575    ///
 576    /// ```rust
 577    /// use minidom::{Element, Node};
 578    ///
 579    /// let mut elem = Element::bare("node", "ns1");
 580    ///
 581    /// elem.append_node(Node::Text("hello".to_owned()));
 582    ///
 583    /// assert_eq!(elem.text(), "hello");
 584    /// ```
 585    pub fn append_node(&mut self, node: Node) {
 586        self.children.push(node);
 587    }
 588
 589    /// Returns the concatenation of all text nodes in the `Element`.
 590    ///
 591    /// # Examples
 592    ///
 593    /// ```rust
 594    /// use minidom::Element;
 595    ///
 596    /// let elem: Element = "<node xmlns=\"ns1\">hello,<split /> world!</node>".parse().unwrap();
 597    ///
 598    /// assert_eq!(elem.text(), "hello, world!");
 599    /// ```
 600    pub fn text(&self) -> String {
 601        self.texts().fold(String::new(), |ret, new| ret + new)
 602    }
 603
 604    /// Returns a reference to the first child element with the specific name and namespace, if it
 605    /// exists in the direct descendants of this `Element`, else returns `None`.
 606    ///
 607    /// # Examples
 608    ///
 609    /// ```rust
 610    /// use minidom::{Element, NSChoice};
 611    ///
 612    /// let elem: Element = r#"<node xmlns="ns"><a/><a xmlns="other_ns" /><b/></node>"#.parse().unwrap();
 613    /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
 614    /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
 615    /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
 616    /// assert_eq!(elem.get_child("c", "ns"), None);
 617    /// assert_eq!(elem.get_child("b", "other_ns"), None);
 618    /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
 619    /// ```
 620    pub fn get_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
 621        &self,
 622        name: N,
 623        namespace: NS,
 624    ) -> Option<&Element> {
 625        let namespace = namespace.into();
 626        for fork in &self.children {
 627            if let Node::Element(ref e) = *fork {
 628                if e.is(name.as_ref(), namespace) {
 629                    return Some(e);
 630                }
 631            }
 632        }
 633        None
 634    }
 635
 636    /// Returns a mutable reference to the first child element with the specific name and namespace,
 637    /// if it exists in the direct descendants of this `Element`, else returns `None`.
 638    pub fn get_child_mut<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
 639        &mut self,
 640        name: N,
 641        namespace: NS,
 642    ) -> Option<&mut Element> {
 643        let namespace = namespace.into();
 644        for fork in &mut self.children {
 645            if let Node::Element(ref mut e) = *fork {
 646                if e.is(name.as_ref(), namespace) {
 647                    return Some(e);
 648                }
 649            }
 650        }
 651        None
 652    }
 653
 654    /// Returns whether a specific child with this name and namespace exists in the direct
 655    /// descendants of the `Element`.
 656    ///
 657    /// # Examples
 658    ///
 659    /// ```rust
 660    /// use minidom::{Element, NSChoice};
 661    ///
 662    /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
 663    /// assert_eq!(elem.has_child("a", "other_ns"), true);
 664    /// assert_eq!(elem.has_child("a", "ns"), true);
 665    /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
 666    /// assert_eq!(elem.has_child("b", "ns"), true);
 667    /// assert_eq!(elem.has_child("b", "other_ns"), false);
 668    /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
 669    /// ```
 670    pub fn has_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
 671        &self,
 672        name: N,
 673        namespace: NS,
 674    ) -> bool {
 675        self.get_child(name, namespace).is_some()
 676    }
 677
 678    /// Removes the first child with this name and namespace, if it exists, and returns an
 679    /// `Option<Element>` containing this child if it succeeds.
 680    /// Returns `None` if no child matches this name and namespace.
 681    ///
 682    /// # Examples
 683    ///
 684    /// ```rust
 685    /// use minidom::{Element, NSChoice};
 686    ///
 687    /// let mut elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
 688    /// assert!(elem.remove_child("a", "ns").unwrap().is("a", "ns"));
 689    /// assert!(elem.remove_child("a", "ns").is_none());
 690    /// assert!(elem.remove_child("inexistent", "inexistent").is_none());
 691    /// ```
 692    pub fn remove_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
 693        &mut self,
 694        name: N,
 695        namespace: NS,
 696    ) -> Option<Element> {
 697        let name = name.as_ref();
 698        let namespace = namespace.into();
 699        let idx = self.children.iter().position(|x| {
 700            if let Node::Element(ref elm) = x {
 701                elm.is(name, namespace)
 702            } else {
 703                false
 704            }
 705        })?;
 706        self.children.remove(idx).into_element()
 707    }
 708
 709    /// Remove the leading nodes up to the first child element and
 710    /// return it
 711    pub fn unshift_child(&mut self) -> Option<Element> {
 712        while self.children.len() > 0 {
 713            if let Some(el) = self.children.remove(0).into_element() {
 714                return Some(el);
 715            }
 716        }
 717
 718        None
 719    }
 720}
 721
 722/// An iterator over references to child elements of an `Element`.
 723pub struct Children<'a> {
 724    iter: slice::Iter<'a, Node>,
 725}
 726
 727impl<'a> Iterator for Children<'a> {
 728    type Item = &'a Element;
 729
 730    fn next(&mut self) -> Option<&'a Element> {
 731        for item in &mut self.iter {
 732            if let Node::Element(ref child) = *item {
 733                return Some(child);
 734            }
 735        }
 736        None
 737    }
 738}
 739
 740/// An iterator over mutable references to child elements of an `Element`.
 741pub struct ChildrenMut<'a> {
 742    iter: slice::IterMut<'a, Node>,
 743}
 744
 745impl<'a> Iterator for ChildrenMut<'a> {
 746    type Item = &'a mut Element;
 747
 748    fn next(&mut self) -> Option<&'a mut Element> {
 749        for item in &mut self.iter {
 750            if let Node::Element(ref mut child) = *item {
 751                return Some(child);
 752            }
 753        }
 754        None
 755    }
 756}
 757
 758/// An iterator over references to child text nodes of an `Element`.
 759pub struct Texts<'a> {
 760    iter: slice::Iter<'a, Node>,
 761}
 762
 763impl<'a> Iterator for Texts<'a> {
 764    type Item = &'a str;
 765
 766    fn next(&mut self) -> Option<&'a str> {
 767        for item in &mut self.iter {
 768            if let Node::Text(ref child) = *item {
 769                return Some(child);
 770            }
 771        }
 772        None
 773    }
 774}
 775
 776/// An iterator over mutable references to child text nodes of an `Element`.
 777pub struct TextsMut<'a> {
 778    iter: slice::IterMut<'a, Node>,
 779}
 780
 781impl<'a> Iterator for TextsMut<'a> {
 782    type Item = &'a mut String;
 783
 784    fn next(&mut self) -> Option<&'a mut String> {
 785        for item in &mut self.iter {
 786            if let Node::Text(ref mut child) = *item {
 787                return Some(child);
 788            }
 789        }
 790        None
 791    }
 792}
 793
 794/// An iterator over references to all child nodes of an `Element`.
 795pub type Nodes<'a> = slice::Iter<'a, Node>;
 796
 797/// An iterator over mutable references to all child nodes of an `Element`.
 798pub type NodesMut<'a> = slice::IterMut<'a, Node>;
 799
 800/// An iterator over the attributes of an `Element`.
 801pub struct Attrs<'a> {
 802    iter: btree_map::Iter<'a, String, String>,
 803}
 804
 805impl<'a> Iterator for Attrs<'a> {
 806    type Item = (&'a str, &'a str);
 807
 808    fn next(&mut self) -> Option<Self::Item> {
 809        self.iter.next().map(|(x, y)| (x.as_ref(), y.as_ref()))
 810    }
 811}
 812
 813/// An iterator over the attributes of an `Element`, with the values mutable.
 814pub struct AttrsMut<'a> {
 815    iter: btree_map::IterMut<'a, String, String>,
 816}
 817
 818impl<'a> Iterator for AttrsMut<'a> {
 819    type Item = (&'a str, &'a mut String);
 820
 821    fn next(&mut self) -> Option<Self::Item> {
 822        self.iter.next().map(|(x, y)| (x.as_ref(), y))
 823    }
 824}
 825
 826/// A builder for `Element`s.
 827pub struct ElementBuilder {
 828    root: Element,
 829}
 830
 831impl ElementBuilder {
 832    /// Sets a custom prefix. It is not possible to set the same prefix twice.
 833    pub fn prefix<S: Into<Namespace>>(
 834        mut self,
 835        prefix: Prefix,
 836        namespace: S,
 837    ) -> Result<ElementBuilder> {
 838        if self.root.prefixes.get(&prefix).is_some() {
 839            return Err(Error::DuplicatePrefix);
 840        }
 841        self.root.prefixes.insert(prefix, namespace.into());
 842        Ok(self)
 843    }
 844
 845    /// Sets an attribute.
 846    pub fn attr<S: Into<String>, V: IntoAttributeValue>(
 847        mut self,
 848        name: S,
 849        value: V,
 850    ) -> ElementBuilder {
 851        self.root.set_attr(name, value);
 852        self
 853    }
 854
 855    /// Appends anything implementing `Into<Node>` into the tree.
 856    pub fn append<T: Into<Node>>(mut self, node: T) -> ElementBuilder {
 857        self.root.append_node(node.into());
 858        self
 859    }
 860
 861    /// Appends an iterator of things implementing `Into<Node>` into the tree.
 862    pub fn append_all<T: Into<Node>, I: IntoIterator<Item = T>>(
 863        mut self,
 864        iter: I,
 865    ) -> ElementBuilder {
 866        for node in iter {
 867            self.root.append_node(node.into());
 868        }
 869        self
 870    }
 871
 872    /// Builds the `Element`.
 873    pub fn build(self) -> Element {
 874        self.root
 875    }
 876}
 877
 878#[cfg(test)]
 879mod tests {
 880    use super::*;
 881
 882    #[test]
 883    fn test_element_new() {
 884        use std::iter::FromIterator;
 885
 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_from_reader_with_prefixes() {
 983        let xml = b"<foo><bar xmlns='baz'/></foo>";
 984        let elem =
 985            Element::from_reader_with_prefixes(&xml[..], String::from("jabber:client")).unwrap();
 986
 987        let xml2 = b"<foo xmlns='jabber:client'><bar xmlns='baz'/></foo>";
 988        let elem2 = Element::from_reader(&xml2[..]).unwrap();
 989
 990        assert_eq!(elem, elem2);
 991    }
 992
 993    #[test]
 994    fn failure_with_duplicate_namespace() {
 995        let _: Element = r###"<?xml version="1.0" encoding="UTF-8"?>
 996            <wsdl:definitions
 997                    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
 998                    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 999                <wsdl:types>
1000                    <xsd:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
1001                    </xsd:schema>
1002                </wsdl:types>
1003            </wsdl:definitions>
1004        "###
1005        .parse()
1006        .unwrap();
1007    }
1008}