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};
  20
  21use std::collections::{btree_map, BTreeMap};
  22use std::io::Write;
  23
  24use std::borrow::Cow;
  25use std::str;
  26
  27use quick_xml::events::{BytesDecl, BytesEnd, BytesStart, Event};
  28use quick_xml::Reader as EventReader;
  29use quick_xml::Writer as EventWriter;
  30
  31use std::io::BufRead;
  32
  33use std::str::FromStr;
  34
  35use std::slice;
  36
  37/// helper function to escape a `&[u8]` and replace all
  38/// xml special characters (<, >, &, ', ") with their corresponding
  39/// xml escaped value.
  40pub fn escape(raw: &[u8]) -> Cow<[u8]> {
  41    let mut escapes: Vec<(usize, &'static [u8])> = Vec::new();
  42    let mut bytes = raw.iter();
  43    fn to_escape(b: u8) -> bool {
  44        matches!(b, b'<' | b'>' | b'\'' | b'&' | b'"')
  45    }
  46
  47    let mut loc = 0;
  48    while let Some(i) = bytes.position(|&b| to_escape(b)) {
  49        loc += i;
  50        match raw[loc] {
  51            b'<' => escapes.push((loc, b"&lt;")),
  52            b'>' => escapes.push((loc, b"&gt;")),
  53            b'\'' => escapes.push((loc, b"&apos;")),
  54            b'&' => escapes.push((loc, b"&amp;")),
  55            b'"' => escapes.push((loc, b"&quot;")),
  56            _ => unreachable!("Only '<', '>','\', '&' and '\"' are escaped"),
  57        }
  58        loc += 1;
  59    }
  60
  61    if escapes.is_empty() {
  62        Cow::Borrowed(raw)
  63    } else {
  64        let len = raw.len();
  65        let mut v = Vec::with_capacity(len);
  66        let mut start = 0;
  67        for (i, r) in escapes {
  68            v.extend_from_slice(&raw[start..i]);
  69            v.extend_from_slice(r);
  70            start = i + 1;
  71        }
  72
  73        if start < len {
  74            v.extend_from_slice(&raw[start..]);
  75        }
  76        Cow::Owned(v)
  77    }
  78}
  79
  80#[derive(Clone, Eq, Debug)]
  81/// A struct representing a DOM Element.
  82pub struct Element {
  83    name: String,
  84    namespace: String,
  85    /// This is only used when deserializing. If you have to use a custom prefix use
  86    /// `ElementBuilder::prefix`.
  87    prefix: Option<Prefix>,
  88    prefixes: Prefixes,
  89    attributes: BTreeMap<String, String>,
  90    children: Vec<Node>,
  91}
  92
  93impl<'a> From<&'a Element> for String {
  94    fn from(elem: &'a Element) -> String {
  95        let mut writer = Vec::new();
  96        elem.write_to(&mut writer).unwrap();
  97        String::from_utf8(writer).unwrap()
  98    }
  99}
 100
 101impl FromStr for Element {
 102    type Err = Error;
 103
 104    fn from_str(s: &str) -> Result<Element> {
 105        let mut reader = EventReader::from_str(s);
 106        Element::from_reader(&mut reader)
 107    }
 108}
 109
 110impl PartialEq for Element {
 111    fn eq(&self, other: &Self) -> bool {
 112        if self.name() == other.name() && self.ns() == other.ns() && self.attrs().eq(other.attrs())
 113        {
 114            self.nodes()
 115                .zip(other.nodes())
 116                .all(|(node1, node2)| node1 == node2)
 117        } else {
 118            false
 119        }
 120    }
 121}
 122
 123fn ensure_no_prefix<S: AsRef<str>>(s: &S) -> Result<()> {
 124    match s.as_ref().split(':').count() {
 125        1 => Ok(()),
 126        _ => Err(Error::InvalidElement),
 127    }
 128}
 129
 130impl Element {
 131    fn new<P: Into<Prefixes>>(
 132        name: String,
 133        namespace: String,
 134        prefix: Option<Prefix>,
 135        prefixes: P,
 136        attributes: BTreeMap<String, String>,
 137        children: Vec<Node>,
 138    ) -> Element {
 139        ensure_no_prefix(&name).unwrap();
 140        // TODO: Return Result<Element> instead.
 141        Element {
 142            name,
 143            namespace,
 144            prefix,
 145            prefixes: prefixes.into(),
 146            attributes,
 147            children,
 148        }
 149    }
 150
 151    /// Return a builder for an `Element` with the given `name`.
 152    ///
 153    /// # Examples
 154    ///
 155    /// ```rust
 156    /// use minidom::Element;
 157    ///
 158    /// let elem = Element::builder("name", "namespace")
 159    ///                    .attr("name", "value")
 160    ///                    .append("inner")
 161    ///                    .build();
 162    ///
 163    /// assert_eq!(elem.name(), "name");
 164    /// assert_eq!(elem.ns(), "namespace".to_owned());
 165    /// assert_eq!(elem.attr("name"), Some("value"));
 166    /// assert_eq!(elem.attr("inexistent"), None);
 167    /// assert_eq!(elem.text(), "inner");
 168    /// ```
 169    pub fn builder<S: AsRef<str>, NS: Into<String>>(name: S, namespace: NS) -> ElementBuilder {
 170        ElementBuilder {
 171            root: Element::new(
 172                name.as_ref().to_string(),
 173                namespace.into(),
 174                None,
 175                None,
 176                BTreeMap::new(),
 177                Vec::new(),
 178            ),
 179        }
 180    }
 181
 182    /// Returns a bare minimum `Element` with this name.
 183    ///
 184    /// # Examples
 185    ///
 186    /// ```rust
 187    /// use minidom::Element;
 188    ///
 189    /// let bare = Element::bare("name", "namespace");
 190    ///
 191    /// assert_eq!(bare.name(), "name");
 192    /// assert_eq!(bare.ns(), "namespace");
 193    /// assert_eq!(bare.attr("name"), None);
 194    /// assert_eq!(bare.text(), "");
 195    /// ```
 196    pub fn bare<S: Into<String>, NS: Into<String>>(name: S, namespace: NS) -> Element {
 197        Element::new(
 198            name.into(),
 199            namespace.into(),
 200            None,
 201            None,
 202            BTreeMap::new(),
 203            Vec::new(),
 204        )
 205    }
 206
 207    /// Returns a reference to the local name of this element (that is, without a possible prefix).
 208    pub fn name(&self) -> &str {
 209        &self.name
 210    }
 211
 212    /// Returns a reference to the namespace of this element.
 213    pub fn ns(&self) -> String {
 214        self.namespace.clone()
 215    }
 216
 217    /// Returns a reference to the value of the given attribute, if it exists, else `None`.
 218    pub fn attr(&self, name: &str) -> Option<&str> {
 219        if let Some(value) = self.attributes.get(name) {
 220            return Some(value);
 221        }
 222        None
 223    }
 224
 225    /// Returns an iterator over the attributes of this element.
 226    ///
 227    /// # Example
 228    ///
 229    /// ```rust
 230    /// use minidom::Element;
 231    ///
 232    /// let elm: Element = "<elem xmlns=\"ns1\" a=\"b\" />".parse().unwrap();
 233    ///
 234    /// let mut iter = elm.attrs();
 235    ///
 236    /// assert_eq!(iter.next().unwrap(), ("a", "b"));
 237    /// assert_eq!(iter.next(), None);
 238    /// ```
 239    pub fn attrs(&self) -> Attrs {
 240        Attrs {
 241            iter: self.attributes.iter(),
 242        }
 243    }
 244
 245    /// Returns an iterator over the attributes of this element, with the value being a mutable
 246    /// reference.
 247    pub fn attrs_mut(&mut self) -> AttrsMut {
 248        AttrsMut {
 249            iter: self.attributes.iter_mut(),
 250        }
 251    }
 252
 253    /// Modifies the value of an attribute.
 254    pub fn set_attr<S: Into<String>, V: IntoAttributeValue>(&mut self, name: S, val: V) {
 255        let name = name.into();
 256        let val = val.into_attribute_value();
 257
 258        if let Some(value) = self.attributes.get_mut(&name) {
 259            *value = val
 260                .expect("removing existing value via set_attr, this is not yet supported (TODO)"); // TODO
 261            return;
 262        }
 263
 264        if let Some(val) = val {
 265            self.attributes.insert(name, val);
 266        }
 267    }
 268
 269    /// Returns whether the element has the given name and namespace.
 270    ///
 271    /// # Examples
 272    ///
 273    /// ```rust
 274    /// use minidom::{Element, NSChoice};
 275    ///
 276    /// let elem = Element::builder("name", "namespace").build();
 277    ///
 278    /// assert_eq!(elem.is("name", "namespace"), true);
 279    /// assert_eq!(elem.is("name", "wrong"), false);
 280    /// assert_eq!(elem.is("wrong", "namespace"), false);
 281    /// assert_eq!(elem.is("wrong", "wrong"), false);
 282    ///
 283    /// assert_eq!(elem.is("name", NSChoice::OneOf("namespace")), true);
 284    /// assert_eq!(elem.is("name", NSChoice::OneOf("foo")), false);
 285    /// assert_eq!(elem.is("name", NSChoice::AnyOf(&["foo", "namespace"])), true);
 286    /// assert_eq!(elem.is("name", NSChoice::Any), true);
 287    /// ```
 288    pub fn is<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(&self, name: N, namespace: NS) -> bool {
 289        self.name == name.as_ref() && namespace.into().compare(self.namespace.as_ref())
 290    }
 291
 292    /// Returns whether the element has the given 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.has_ns("namespace"), true);
 302    /// assert_eq!(elem.has_ns("wrong"), false);
 303    ///
 304    /// assert_eq!(elem.has_ns(NSChoice::OneOf("namespace")), true);
 305    /// assert_eq!(elem.has_ns(NSChoice::OneOf("foo")), false);
 306    /// assert_eq!(elem.has_ns(NSChoice::AnyOf(&["foo", "namespace"])), true);
 307    /// assert_eq!(elem.has_ns(NSChoice::Any), true);
 308    /// ```
 309    pub fn has_ns<'a, NS: Into<NSChoice<'a>>>(&self, namespace: NS) -> bool {
 310        namespace.into().compare(self.namespace.as_ref())
 311    }
 312
 313    /// Parse a document from an `EventReader`.
 314    pub fn from_reader<R: BufRead>(reader: &mut EventReader<R>) -> Result<Element> {
 315        let mut buf = Vec::new();
 316
 317        let mut prefixes = BTreeMap::new();
 318        let root: Element = loop {
 319            let e = reader.read_event(&mut buf)?;
 320            match e {
 321                Event::Empty(ref e) | Event::Start(ref e) => {
 322                    break build_element(reader, e, &mut prefixes)?;
 323                }
 324                Event::Eof => {
 325                    return Err(Error::EndOfDocument);
 326                }
 327                Event::Comment { .. } => {
 328                    return Err(Error::NoComments);
 329                }
 330                Event::Text { .. }
 331                | Event::End { .. }
 332                | Event::CData { .. }
 333                | Event::Decl { .. }
 334                | Event::PI { .. }
 335                | Event::DocType { .. } => (), // TODO: may need more errors
 336            }
 337        };
 338
 339        let mut stack = vec![root];
 340        let mut prefix_stack = vec![prefixes];
 341
 342        loop {
 343            match reader.read_event(&mut buf)? {
 344                Event::Empty(ref e) => {
 345                    let mut prefixes = prefix_stack.last().unwrap().clone();
 346                    let elem = build_element(reader, e, &mut prefixes)?;
 347                    // Since there is no Event::End after, directly append it to the current node
 348                    stack.last_mut().unwrap().append_child(elem);
 349                }
 350                Event::Start(ref e) => {
 351                    let mut prefixes = prefix_stack.last().unwrap().clone();
 352                    let elem = build_element(reader, e, &mut prefixes)?;
 353                    stack.push(elem);
 354                    prefix_stack.push(prefixes);
 355                }
 356                Event::End(ref e) => {
 357                    if stack.len() <= 1 {
 358                        break;
 359                    }
 360                    let prefixes = prefix_stack.pop().unwrap();
 361                    let elem = stack.pop().unwrap();
 362                    if let Some(to) = stack.last_mut() {
 363                        // TODO: check whether this is correct, we are comparing &[u8]s, not &strs
 364                        let elem_name = e.name();
 365                        let mut split_iter = elem_name.splitn(2, |u| *u == 0x3A);
 366                        let possible_prefix = split_iter.next().unwrap(); // Can't be empty.
 367                        let opening_prefix = {
 368                            let mut tmp: Option<Option<String>> = None;
 369                            for (prefix, ns) in prefixes {
 370                                if ns == elem.namespace {
 371                                    tmp = Some(prefix.clone());
 372                                    break;
 373                                }
 374                            }
 375                            match tmp {
 376                                Some(prefix) => prefix,
 377                                None => return Err(Error::InvalidPrefix),
 378                            }
 379                        };
 380                        match split_iter.next() {
 381                            // There is a prefix on the closing tag
 382                            Some(name) => {
 383                                // Does the closing prefix match the opening prefix?
 384                                match opening_prefix {
 385                                    Some(prefix) if possible_prefix == prefix.as_bytes() => (),
 386                                    _ => return Err(Error::InvalidElementClosed),
 387                                }
 388                                // Does the closing tag name match the opening tag name?
 389                                if name != elem.name().as_bytes() {
 390                                    return Err(Error::InvalidElementClosed);
 391                                }
 392                            }
 393                            // There was no prefix on the closing tag
 394                            None => {
 395                                // Is there a prefix on the opening tag?
 396                                if opening_prefix.is_some() {
 397                                    return Err(Error::InvalidElementClosed);
 398                                }
 399                                // Does the opening tag name match the closing one?
 400                                if possible_prefix != elem.name().as_bytes() {
 401                                    return Err(Error::InvalidElementClosed);
 402                                }
 403                            }
 404                        }
 405                        to.append_child(elem);
 406                    }
 407                }
 408                Event::Text(s) => {
 409                    let text = s.unescape_and_decode(reader)?;
 410                    if !text.is_empty() {
 411                        let current_elem = stack.last_mut().unwrap();
 412                        current_elem.append_text_node(text);
 413                    }
 414                }
 415                Event::CData(s) => {
 416                    let text = reader.decode(&s)?.to_owned();
 417                    if !text.is_empty() {
 418                        let current_elem = stack.last_mut().unwrap();
 419                        current_elem.append_text_node(text);
 420                    }
 421                }
 422                Event::Eof => {
 423                    break;
 424                }
 425                Event::Comment(_) => return Err(Error::NoComments),
 426                Event::Decl { .. } | Event::PI { .. } | Event::DocType { .. } => (),
 427            }
 428        }
 429        Ok(stack.pop().unwrap())
 430    }
 431
 432    /// Output a document to a `Writer`.
 433    pub fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
 434        self.to_writer(&mut EventWriter::new(writer))
 435    }
 436
 437    /// Output a document to a `Writer`.
 438    pub fn write_to_decl<W: Write>(&self, writer: &mut W) -> Result<()> {
 439        self.to_writer_decl(&mut EventWriter::new(writer))
 440    }
 441
 442    /// Output the document to quick-xml `Writer`
 443    pub fn to_writer<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<()> {
 444        self.write_to_inner(writer, &mut BTreeMap::new())
 445    }
 446
 447    /// Output the document to quick-xml `Writer`
 448    pub fn to_writer_decl<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<()> {
 449        writer.write_event(Event::Decl(BytesDecl::new(b"1.0", Some(b"utf-8"), None)))?;
 450        self.write_to_inner(writer, &mut BTreeMap::new())
 451    }
 452
 453    /// Like `write_to()` but without the `<?xml?>` prelude
 454    pub fn write_to_inner<W: Write>(
 455        &self,
 456        writer: &mut EventWriter<W>,
 457        all_prefixes: &mut BTreeMap<Prefix, Namespace>,
 458    ) -> Result<()> {
 459        let local_prefixes: &BTreeMap<Option<String>, String> = self.prefixes.declared_prefixes();
 460
 461        // Element namespace
 462        // If the element prefix hasn't been set yet via a custom prefix, add it.
 463        let mut existing_self_prefix: Option<Option<String>> = None;
 464        for (prefix, ns) in local_prefixes.iter().chain(all_prefixes.iter()) {
 465            if ns == &self.namespace {
 466                existing_self_prefix = Some(prefix.clone());
 467            }
 468        }
 469
 470        let mut all_keys = all_prefixes.keys().cloned();
 471        let mut local_keys = local_prefixes.keys().cloned();
 472        let self_prefix: (Option<String>, bool) = match existing_self_prefix {
 473            // No prefix exists already for our namespace
 474            None => {
 475                if !local_keys.any(|p| p.is_none()) {
 476                    // Use the None prefix if available
 477                    (None, true)
 478                } else {
 479                    // Otherwise generate one. Check if it isn't already used, if so increase the
 480                    // number until we find a suitable one.
 481                    let mut prefix_n = 0u8;
 482                    while all_keys.any(|p| p == Some(format!("ns{}", prefix_n))) {
 483                        prefix_n += 1;
 484                    }
 485                    (Some(format!("ns{}", prefix_n)), true)
 486                }
 487            }
 488            // Some prefix has already been declared (or is going to be) for our namespace. We
 489            // don't need to declare a new one. We do however need to remember which one to use in
 490            // the tag name.
 491            Some(prefix) => (prefix, false),
 492        };
 493
 494        let name = match self_prefix {
 495            (Some(ref prefix), _) => Cow::Owned(format!("{}:{}", prefix, self.name)),
 496            _ => Cow::Borrowed(&self.name),
 497        };
 498        let mut start = BytesStart::borrowed(name.as_bytes(), name.len());
 499
 500        // Write self prefix if necessary
 501        match self_prefix {
 502            (Some(ref p), true) => {
 503                let key = format!("xmlns:{}", p);
 504                start.push_attribute((key.as_bytes(), self.namespace.as_bytes()));
 505                all_prefixes.insert(self_prefix.0, self.namespace.clone());
 506            }
 507            (None, true) => {
 508                let key = String::from("xmlns");
 509                start.push_attribute((key.as_bytes(), self.namespace.as_bytes()));
 510                all_prefixes.insert(self_prefix.0, self.namespace.clone());
 511            }
 512            _ => (),
 513        };
 514
 515        // Custom prefixes/namespace sets
 516        for (prefix, ns) in local_prefixes {
 517            match all_prefixes.get(prefix) {
 518                p @ Some(_) if p == prefix.as_ref() => (),
 519                _ => {
 520                    let key = match prefix {
 521                        None => String::from("xmlns"),
 522                        Some(p) => format!("xmlns:{}", p),
 523                    };
 524
 525                    start.push_attribute((key.as_bytes(), ns.as_ref()));
 526                    all_prefixes.insert(prefix.clone(), ns.clone());
 527                }
 528            }
 529        }
 530
 531        for (key, value) in &self.attributes {
 532            start.push_attribute((key.as_bytes(), escape(value.as_bytes()).as_ref()));
 533        }
 534
 535        if self.children.is_empty() {
 536            writer.write_event(Event::Empty(start))?;
 537            return Ok(());
 538        }
 539
 540        writer.write_event(Event::Start(start))?;
 541
 542        for child in &self.children {
 543            child.write_to_inner(writer, &mut all_prefixes.clone())?;
 544        }
 545
 546        writer.write_event(Event::End(BytesEnd::borrowed(name.as_bytes())))?;
 547        Ok(())
 548    }
 549
 550    /// Returns an iterator over references to every child node of this element.
 551    ///
 552    /// # Examples
 553    ///
 554    /// ```rust
 555    /// use minidom::Element;
 556    ///
 557    /// let elem: Element = "<root xmlns=\"ns1\">a<c1 />b<c2 />c</root>".parse().unwrap();
 558    ///
 559    /// let mut iter = elem.nodes();
 560    ///
 561    /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "a");
 562    /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c1");
 563    /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "b");
 564    /// assert_eq!(iter.next().unwrap().as_element().unwrap().name(), "c2");
 565    /// assert_eq!(iter.next().unwrap().as_text().unwrap(), "c");
 566    /// assert_eq!(iter.next(), None);
 567    /// ```
 568    #[inline]
 569    pub fn nodes(&self) -> Nodes {
 570        self.children.iter()
 571    }
 572
 573    /// Returns an iterator over mutable references to every child node of this element.
 574    #[inline]
 575    pub fn nodes_mut(&mut self) -> NodesMut {
 576        self.children.iter_mut()
 577    }
 578
 579    /// Returns an iterator over references to every child element of this element.
 580    ///
 581    /// # Examples
 582    ///
 583    /// ```rust
 584    /// use minidom::Element;
 585    ///
 586    /// let elem: Element = "<root xmlns=\"ns1\">hello<child1 xmlns=\"ns1\"/>this<child2 xmlns=\"ns1\"/>is<child3 xmlns=\"ns1\"/>ignored</root>".parse().unwrap();
 587    ///
 588    /// let mut iter = elem.children();
 589    /// assert_eq!(iter.next().unwrap().name(), "child1");
 590    /// assert_eq!(iter.next().unwrap().name(), "child2");
 591    /// assert_eq!(iter.next().unwrap().name(), "child3");
 592    /// assert_eq!(iter.next(), None);
 593    /// ```
 594    #[inline]
 595    pub fn children(&self) -> Children {
 596        Children {
 597            iter: self.children.iter(),
 598        }
 599    }
 600
 601    /// Returns an iterator over mutable references to every child element of this element.
 602    #[inline]
 603    pub fn children_mut(&mut self) -> ChildrenMut {
 604        ChildrenMut {
 605            iter: self.children.iter_mut(),
 606        }
 607    }
 608
 609    /// Returns an iterator over references to every text node of this element.
 610    ///
 611    /// # Examples
 612    ///
 613    /// ```rust
 614    /// use minidom::Element;
 615    ///
 616    /// let elem: Element = "<root xmlns=\"ns1\">hello<c /> world!</root>".parse().unwrap();
 617    ///
 618    /// let mut iter = elem.texts();
 619    /// assert_eq!(iter.next().unwrap(), "hello");
 620    /// assert_eq!(iter.next().unwrap(), " world!");
 621    /// assert_eq!(iter.next(), None);
 622    /// ```
 623    #[inline]
 624    pub fn texts(&self) -> Texts {
 625        Texts {
 626            iter: self.children.iter(),
 627        }
 628    }
 629
 630    /// Returns an iterator over mutable references to every text node of this element.
 631    #[inline]
 632    pub fn texts_mut(&mut self) -> TextsMut {
 633        TextsMut {
 634            iter: self.children.iter_mut(),
 635        }
 636    }
 637
 638    /// Appends a child node to the `Element`, returning the appended node.
 639    ///
 640    /// # Examples
 641    ///
 642    /// ```rust
 643    /// use minidom::Element;
 644    ///
 645    /// let mut elem = Element::bare("root", "ns1");
 646    ///
 647    /// assert_eq!(elem.children().count(), 0);
 648    ///
 649    /// elem.append_child(Element::bare("child", "ns1"));
 650    ///
 651    /// {
 652    ///     let mut iter = elem.children();
 653    ///     assert_eq!(iter.next().unwrap().name(), "child");
 654    ///     assert_eq!(iter.next(), None);
 655    /// }
 656    ///
 657    /// let child = elem.append_child(Element::bare("new", "ns1"));
 658    ///
 659    /// assert_eq!(child.name(), "new");
 660    /// ```
 661    pub fn append_child(&mut self, child: Element) -> &mut Element {
 662        self.children.push(Node::Element(child));
 663        if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
 664            cld
 665        } else {
 666            unreachable!()
 667        }
 668    }
 669
 670    /// Appends a text node to an `Element`.
 671    ///
 672    /// # Examples
 673    ///
 674    /// ```rust
 675    /// use minidom::Element;
 676    ///
 677    /// let mut elem = Element::bare("node", "ns1");
 678    ///
 679    /// assert_eq!(elem.text(), "");
 680    ///
 681    /// elem.append_text_node("text");
 682    ///
 683    /// assert_eq!(elem.text(), "text");
 684    /// ```
 685    pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
 686        self.children.push(Node::Text(child.into()));
 687    }
 688
 689    /// Appends a node to an `Element`.
 690    ///
 691    /// # Examples
 692    ///
 693    /// ```rust
 694    /// use minidom::{Element, Node};
 695    ///
 696    /// let mut elem = Element::bare("node", "ns1");
 697    ///
 698    /// elem.append_node(Node::Text("hello".to_owned()));
 699    ///
 700    /// assert_eq!(elem.text(), "hello");
 701    /// ```
 702    pub fn append_node(&mut self, node: Node) {
 703        self.children.push(node);
 704    }
 705
 706    /// Returns the concatenation of all text nodes in the `Element`.
 707    ///
 708    /// # Examples
 709    ///
 710    /// ```rust
 711    /// use minidom::Element;
 712    ///
 713    /// let elem: Element = "<node xmlns=\"ns1\">hello,<split /> world!</node>".parse().unwrap();
 714    ///
 715    /// assert_eq!(elem.text(), "hello, world!");
 716    /// ```
 717    pub fn text(&self) -> String {
 718        self.texts().fold(String::new(), |ret, new| ret + new)
 719    }
 720
 721    /// Returns a reference to the first child element with the specific name and namespace, if it
 722    /// exists in the direct descendants of this `Element`, else returns `None`.
 723    ///
 724    /// # Examples
 725    ///
 726    /// ```rust
 727    /// use minidom::{Element, NSChoice};
 728    ///
 729    /// let elem: Element = r#"<node xmlns="ns"><a/><a xmlns="other_ns" /><b/></node>"#.parse().unwrap();
 730    /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
 731    /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
 732    /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
 733    /// assert_eq!(elem.get_child("c", "ns"), None);
 734    /// assert_eq!(elem.get_child("b", "other_ns"), None);
 735    /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
 736    /// ```
 737    pub fn get_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
 738        &self,
 739        name: N,
 740        namespace: NS,
 741    ) -> Option<&Element> {
 742        let namespace = namespace.into();
 743        for fork in &self.children {
 744            if let Node::Element(ref e) = *fork {
 745                if e.is(name.as_ref(), namespace) {
 746                    return Some(e);
 747                }
 748            }
 749        }
 750        None
 751    }
 752
 753    /// Returns a mutable reference to the first child element with the specific name and namespace,
 754    /// if it exists in the direct descendants of this `Element`, else returns `None`.
 755    pub fn get_child_mut<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
 756        &mut self,
 757        name: N,
 758        namespace: NS,
 759    ) -> Option<&mut Element> {
 760        let namespace = namespace.into();
 761        for fork in &mut self.children {
 762            if let Node::Element(ref mut e) = *fork {
 763                if e.is(name.as_ref(), namespace) {
 764                    return Some(e);
 765                }
 766            }
 767        }
 768        None
 769    }
 770
 771    /// Returns whether a specific child with this name and namespace exists in the direct
 772    /// descendants of the `Element`.
 773    ///
 774    /// # Examples
 775    ///
 776    /// ```rust
 777    /// use minidom::{Element, NSChoice};
 778    ///
 779    /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
 780    /// assert_eq!(elem.has_child("a", "other_ns"), true);
 781    /// assert_eq!(elem.has_child("a", "ns"), true);
 782    /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
 783    /// assert_eq!(elem.has_child("b", "ns"), true);
 784    /// assert_eq!(elem.has_child("b", "other_ns"), false);
 785    /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
 786    /// ```
 787    pub fn has_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
 788        &self,
 789        name: N,
 790        namespace: NS,
 791    ) -> bool {
 792        self.get_child(name, namespace).is_some()
 793    }
 794
 795    /// Removes the first child with this name and namespace, if it exists, and returns an
 796    /// `Option<Element>` containing this child if it succeeds.
 797    /// Returns `None` if no child matches this name and namespace.
 798    ///
 799    /// # Examples
 800    ///
 801    /// ```rust
 802    /// use minidom::{Element, NSChoice};
 803    ///
 804    /// let mut elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
 805    /// assert!(elem.remove_child("a", "ns").unwrap().is("a", "ns"));
 806    /// assert!(elem.remove_child("a", "ns").is_none());
 807    /// assert!(elem.remove_child("inexistent", "inexistent").is_none());
 808    /// ```
 809    pub fn remove_child<'a, N: AsRef<str>, NS: Into<NSChoice<'a>>>(
 810        &mut self,
 811        name: N,
 812        namespace: NS,
 813    ) -> Option<Element> {
 814        let name = name.as_ref();
 815        let namespace = namespace.into();
 816        let idx = self.children.iter().position(|x| {
 817            if let Node::Element(ref elm) = x {
 818                elm.is(name, namespace)
 819            } else {
 820                false
 821            }
 822        })?;
 823        self.children.remove(idx).into_element()
 824    }
 825}
 826
 827fn split_element_name<S: AsRef<str>>(s: S) -> Result<(Option<String>, String)> {
 828    let name_parts = s.as_ref().split(':').collect::<Vec<&str>>();
 829    match name_parts.len() {
 830        2 => Ok((Some(name_parts[0].to_owned()), name_parts[1].to_owned())),
 831        1 => Ok((None, name_parts[0].to_owned())),
 832        _ => Err(Error::InvalidElement),
 833    }
 834}
 835
 836fn build_element<R: BufRead>(
 837    reader: &EventReader<R>,
 838    event: &BytesStart,
 839    prefixes: &mut BTreeMap<Prefix, Namespace>,
 840) -> Result<Element> {
 841    let (prefix, name) = split_element_name(str::from_utf8(event.name())?)?;
 842    let mut local_prefixes = BTreeMap::new();
 843
 844    let attributes = event
 845        .attributes()
 846        .map(|o| {
 847            let o = o?;
 848            let key = str::from_utf8(o.key)?.to_owned();
 849            let value = o.unescape_and_decode_value(reader)?;
 850            Ok((key, value))
 851        })
 852        .filter(|o| match *o {
 853            Ok((ref key, ref value)) if key == "xmlns" => {
 854                local_prefixes.insert(None, value.clone());
 855                prefixes.insert(None, value.clone());
 856                false
 857            }
 858            Ok((ref key, ref value)) if key.starts_with("xmlns:") => {
 859                local_prefixes.insert(Some(key[6..].to_owned()), value.to_owned());
 860                prefixes.insert(Some(key[6..].to_owned()), value.to_owned());
 861                false
 862            }
 863            _ => true,
 864        })
 865        .collect::<Result<BTreeMap<String, String>>>()?;
 866
 867    let namespace: &String = {
 868        if let Some(namespace) = local_prefixes.get(&prefix) {
 869            namespace
 870        } else if let Some(namespace) = prefixes.get(&prefix) {
 871            namespace
 872        } else {
 873            return Err(Error::MissingNamespace);
 874        }
 875    };
 876
 877    Ok(Element::new(
 878        name,
 879        namespace.clone(),
 880        // Note that this will always be Some(_) as we can't distinguish between the None case and
 881        // Some(None). At least we make sure the prefix has a namespace associated.
 882        Some(prefix),
 883        local_prefixes,
 884        attributes,
 885        Vec::new(),
 886    ))
 887}
 888
 889/// An iterator over references to child elements of an `Element`.
 890pub struct Children<'a> {
 891    iter: slice::Iter<'a, Node>,
 892}
 893
 894impl<'a> Iterator for Children<'a> {
 895    type Item = &'a Element;
 896
 897    fn next(&mut self) -> Option<&'a Element> {
 898        for item in &mut self.iter {
 899            if let Node::Element(ref child) = *item {
 900                return Some(child);
 901            }
 902        }
 903        None
 904    }
 905}
 906
 907/// An iterator over mutable references to child elements of an `Element`.
 908pub struct ChildrenMut<'a> {
 909    iter: slice::IterMut<'a, Node>,
 910}
 911
 912impl<'a> Iterator for ChildrenMut<'a> {
 913    type Item = &'a mut Element;
 914
 915    fn next(&mut self) -> Option<&'a mut Element> {
 916        for item in &mut self.iter {
 917            if let Node::Element(ref mut child) = *item {
 918                return Some(child);
 919            }
 920        }
 921        None
 922    }
 923}
 924
 925/// An iterator over references to child text nodes of an `Element`.
 926pub struct Texts<'a> {
 927    iter: slice::Iter<'a, Node>,
 928}
 929
 930impl<'a> Iterator for Texts<'a> {
 931    type Item = &'a str;
 932
 933    fn next(&mut self) -> Option<&'a str> {
 934        for item in &mut self.iter {
 935            if let Node::Text(ref child) = *item {
 936                return Some(child);
 937            }
 938        }
 939        None
 940    }
 941}
 942
 943/// An iterator over mutable references to child text nodes of an `Element`.
 944pub struct TextsMut<'a> {
 945    iter: slice::IterMut<'a, Node>,
 946}
 947
 948impl<'a> Iterator for TextsMut<'a> {
 949    type Item = &'a mut String;
 950
 951    fn next(&mut self) -> Option<&'a mut String> {
 952        for item in &mut self.iter {
 953            if let Node::Text(ref mut child) = *item {
 954                return Some(child);
 955            }
 956        }
 957        None
 958    }
 959}
 960
 961/// An iterator over references to all child nodes of an `Element`.
 962pub type Nodes<'a> = slice::Iter<'a, Node>;
 963
 964/// An iterator over mutable references to all child nodes of an `Element`.
 965pub type NodesMut<'a> = slice::IterMut<'a, Node>;
 966
 967/// An iterator over the attributes of an `Element`.
 968pub struct Attrs<'a> {
 969    iter: btree_map::Iter<'a, String, String>,
 970}
 971
 972impl<'a> Iterator for Attrs<'a> {
 973    type Item = (&'a str, &'a str);
 974
 975    fn next(&mut self) -> Option<Self::Item> {
 976        self.iter.next().map(|(x, y)| (x.as_ref(), y.as_ref()))
 977    }
 978}
 979
 980/// An iterator over the attributes of an `Element`, with the values mutable.
 981pub struct AttrsMut<'a> {
 982    iter: btree_map::IterMut<'a, String, String>,
 983}
 984
 985impl<'a> Iterator for AttrsMut<'a> {
 986    type Item = (&'a str, &'a mut String);
 987
 988    fn next(&mut self) -> Option<Self::Item> {
 989        self.iter.next().map(|(x, y)| (x.as_ref(), y))
 990    }
 991}
 992
 993/// A builder for `Element`s.
 994pub struct ElementBuilder {
 995    root: Element,
 996}
 997
 998impl ElementBuilder {
 999    /// Sets a custom prefix. It is not possible to set the same prefix twice.
1000    pub fn prefix<S: Into<Namespace>>(
1001        mut self,
1002        prefix: Prefix,
1003        namespace: S,
1004    ) -> Result<ElementBuilder> {
1005        if self.root.prefixes.get(&prefix).is_some() {
1006            return Err(Error::DuplicatePrefix);
1007        }
1008        self.root.prefixes.insert(prefix, namespace.into());
1009        Ok(self)
1010    }
1011
1012    /// Sets an attribute.
1013    pub fn attr<S: Into<String>, V: IntoAttributeValue>(
1014        mut self,
1015        name: S,
1016        value: V,
1017    ) -> ElementBuilder {
1018        self.root.set_attr(name, value);
1019        self
1020    }
1021
1022    /// Appends anything implementing `Into<Node>` into the tree.
1023    pub fn append<T: Into<Node>>(mut self, node: T) -> ElementBuilder {
1024        self.root.append_node(node.into());
1025        self
1026    }
1027
1028    /// Appends an iterator of things implementing `Into<Node>` into the tree.
1029    pub fn append_all<T: Into<Node>, I: IntoIterator<Item = T>>(
1030        mut self,
1031        iter: I,
1032    ) -> ElementBuilder {
1033        for node in iter {
1034            self.root.append_node(node.into());
1035        }
1036        self
1037    }
1038
1039    /// Builds the `Element`.
1040    pub fn build(self) -> Element {
1041        self.root
1042    }
1043}
1044
1045#[cfg(test)]
1046mod tests {
1047    use super::*;
1048
1049    #[test]
1050    fn test_element_new() {
1051        use std::iter::FromIterator;
1052
1053        let elem = Element::new(
1054            "name".to_owned(),
1055            "namespace".to_owned(),
1056            None,
1057            (None, "namespace".to_owned()),
1058            BTreeMap::from_iter(vec![("name".to_string(), "value".to_string())].into_iter()),
1059            Vec::new(),
1060        );
1061
1062        assert_eq!(elem.name(), "name");
1063        assert_eq!(elem.ns(), "namespace".to_owned());
1064        assert_eq!(elem.attr("name"), Some("value"));
1065        assert_eq!(elem.attr("inexistent"), None);
1066    }
1067
1068    #[test]
1069    fn test_from_reader_simple() {
1070        let xml = "<foo xmlns='ns1'></foo>";
1071        let mut reader = EventReader::from_str(xml);
1072        let elem = Element::from_reader(&mut reader);
1073
1074        let elem2 = Element::builder("foo", "ns1").build();
1075
1076        assert_eq!(elem.unwrap(), elem2);
1077    }
1078
1079    #[test]
1080    fn test_from_reader_nested() {
1081        let xml = "<foo xmlns='ns1'><bar xmlns='ns1' baz='qxx' /></foo>";
1082        let mut reader = EventReader::from_str(xml);
1083        let elem = Element::from_reader(&mut reader);
1084
1085        let nested = Element::builder("bar", "ns1").attr("baz", "qxx").build();
1086        let elem2 = Element::builder("foo", "ns1").append(nested).build();
1087
1088        assert_eq!(elem.unwrap(), elem2);
1089    }
1090
1091    #[test]
1092    fn test_from_reader_with_prefix() {
1093        let xml = "<foo xmlns='ns1'><prefix:bar xmlns:prefix='ns1' baz='qxx' /></foo>";
1094        let mut reader = EventReader::from_str(xml);
1095        let elem = Element::from_reader(&mut reader);
1096
1097        let nested = Element::builder("bar", "ns1").attr("baz", "qxx").build();
1098        let elem2 = Element::builder("foo", "ns1").append(nested).build();
1099
1100        assert_eq!(elem.unwrap(), elem2);
1101    }
1102
1103    #[test]
1104    fn test_from_reader_split_prefix() {
1105        let xml = "<foo:bar xmlns:foo='ns1'/>";
1106        let mut reader = EventReader::from_str(xml);
1107        let elem = Element::from_reader(&mut reader).unwrap();
1108
1109        assert_eq!(elem.name(), String::from("bar"));
1110        assert_eq!(elem.ns(), String::from("ns1"));
1111        // Ensure the prefix is properly added to the store
1112        assert_eq!(
1113            elem.prefixes.get(&Some(String::from("foo"))),
1114            Some(&String::from("ns1"))
1115        );
1116    }
1117
1118    #[test]
1119    fn parses_spectest_xml() {
1120        // From: https://gitlab.com/lumi/minidom-rs/issues/8
1121        let xml = r#"
1122            <rng:grammar xmlns:rng="http://relaxng.org/ns/structure/1.0">
1123                <rng:name xmlns:rng="http://relaxng.org/ns/structure/1.0"></rng:name>
1124            </rng:grammar>
1125        "#;
1126        let mut reader = EventReader::from_str(xml);
1127        let _ = Element::from_reader(&mut reader).unwrap();
1128    }
1129
1130    #[test]
1131    fn does_not_unescape_cdata() {
1132        let xml = "<test xmlns='test'><![CDATA[&apos;&gt;blah<blah>]]></test>";
1133        let mut reader = EventReader::from_str(xml);
1134        let elem = Element::from_reader(&mut reader).unwrap();
1135        assert_eq!(elem.text(), "&apos;&gt;blah<blah>");
1136    }
1137
1138    #[test]
1139    fn test_compare_all_ns() {
1140        let xml = "<foo xmlns='foo' xmlns:bar='baz'><bar:meh xmlns:bar='baz' /></foo>";
1141        let mut reader = EventReader::from_str(xml);
1142        let elem = Element::from_reader(&mut reader).unwrap();
1143
1144        let elem2 = elem.clone();
1145
1146        let xml3 = "<foo xmlns='foo'><bar:meh xmlns:bar='baz'/></foo>";
1147        let mut reader3 = EventReader::from_str(xml3);
1148        let elem3 = Element::from_reader(&mut reader3).unwrap();
1149
1150        let xml4 = "<prefix:foo xmlns:prefix='foo'><bar:meh xmlns:bar='baz'/></prefix:foo>";
1151        let mut reader4 = EventReader::from_str(xml4);
1152        let elem4 = Element::from_reader(&mut reader4).unwrap();
1153
1154        assert_eq!(elem, elem2);
1155        assert_eq!(elem, elem3);
1156        assert_eq!(elem, elem4);
1157    }
1158}