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