element.rs

  1//! Provides an `Element` type, which represents DOM nodes, and a builder to create them with.
  2
  3use std::io::prelude::*;
  4use std::io::Cursor;
  5
  6use std::fmt;
  7
  8use error::Error;
  9
 10use attribute::Attribute;
 11
 12use xml::reader::{XmlEvent as ReaderEvent, EventReader};
 13use xml::writer::{XmlEvent as WriterEvent, EventWriter};
 14use xml::name::Name;
 15use xml::namespace::NS_NO_PREFIX;
 16
 17use std::str::FromStr;
 18
 19use std::slice;
 20
 21use convert::{IntoElements, IntoAttributeValue, ElementEmitter};
 22
 23#[derive(Clone, Eq)]
 24/// A struct representing a DOM Element.
 25pub struct Element {
 26    name: String,
 27    namespace: Option<String>,
 28    attributes: Vec<Attribute>,
 29    children: Vec<Node>,
 30}
 31
 32impl PartialEq for Element {
 33    fn eq(&self, other: &Element) -> bool {
 34        let mut my_attr = self.attributes.clone();
 35        my_attr.sort();
 36        let mut other_attr = other.attributes.clone();
 37        other_attr.sort();
 38
 39        self.name == other.name &&
 40        self.namespace == other.namespace &&
 41        my_attr == other_attr &&
 42        self.children == other.children
 43    }
 44}
 45
 46impl fmt::Debug for Element {
 47    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 48        write!(fmt, "<{}", self.name)?;
 49        if let Some(ref ns) = self.namespace {
 50            write!(fmt, " xmlns=\"{}\"", ns)?;
 51        }
 52        for attr in &self.attributes {
 53            write!(fmt, " {}", attr)?;
 54        }
 55        if self.children.is_empty() {
 56            write!(fmt, "/>")?;
 57        }
 58        else {
 59            write!(fmt, ">")?;
 60            for child in &self.children {
 61                match *child {
 62                    Node::Element(ref e) => {
 63                        write!(fmt, "{:?}", e)?;
 64                    },
 65                    Node::Text(ref s) => {
 66                        write!(fmt, "{}", s)?;
 67                    },
 68                }
 69            }
 70            write!(fmt, "</{}>", self.name)?;
 71        }
 72        Ok(())
 73    }
 74}
 75
 76impl FromStr for Element {
 77    type Err = Error;
 78
 79    fn from_str(s: &str) -> Result<Element, Error> {
 80        let mut reader = EventReader::new(Cursor::new(s));
 81        Element::from_reader(&mut reader)
 82    }
 83}
 84
 85/// A node in an element tree.
 86#[derive(Clone, Debug, PartialEq, Eq)]
 87pub enum Node {
 88    /// An `Element`.
 89    Element(Element),
 90    /// A text node.
 91    Text(String),
 92}
 93
 94impl Element {
 95    fn new(name: String, namespace: Option<String>, attributes: Vec<Attribute>, children: Vec<Node>) -> Element {
 96        Element {
 97            name: name,
 98            namespace: namespace,
 99            attributes: attributes,
100            children: children,
101        }
102    }
103
104    /// Return a builder for an `Element` with the given `name`.
105    ///
106    /// # Examples
107    ///
108    /// ```
109    /// use minidom::Element;
110    ///
111    /// let elem = Element::builder("name")
112    ///                    .ns("namespace")
113    ///                    .attr("name", "value")
114    ///                    .append("inner")
115    ///                    .build();
116    ///
117    /// assert_eq!(elem.name(), "name");
118    /// assert_eq!(elem.ns(), Some("namespace"));
119    /// assert_eq!(elem.attr("name"), Some("value"));
120    /// assert_eq!(elem.attr("inexistent"), None);
121    /// assert_eq!(elem.text(), "inner");
122    /// ```
123    pub fn builder<S: Into<String>>(name: S) -> ElementBuilder {
124        ElementBuilder {
125            root: Element::new(name.into(), None, Vec::new(), Vec::new()),
126        }
127    }
128
129    /// Returns a bare minimum `Element` with this name.
130    ///
131    /// # Examples
132    ///
133    /// ```
134    /// use minidom::Element;
135    ///
136    /// let bare = Element::bare("name");
137    ///
138    /// assert_eq!(bare.name(), "name");
139    /// assert_eq!(bare.ns(), None);
140    /// assert_eq!(bare.attr("name"), None);
141    /// assert_eq!(bare.text(), "");
142    /// ```
143    pub fn bare<S: Into<String>>(name: S) -> Element {
144        Element {
145            name: name.into(),
146            namespace: None,
147            attributes: Vec::new(),
148            children: Vec::new(),
149        }
150    }
151
152    /// Returns a reference to the name of this element.
153    pub fn name(&self) -> &str {
154        &self.name
155    }
156
157    /// Returns a reference to the namespace of this element, if it has one, else `None`.
158    pub fn ns(&self) -> Option<&str> {
159        self.namespace.as_ref()
160                      .map(String::as_ref)
161    }
162
163    /// Returns a reference to the value of the given attribute, if it exists, else `None`.
164    pub fn attr(&self, name: &str) -> Option<&str> {
165        for attr in &self.attributes {
166            if attr.name == name {
167                return Some(&attr.value);
168            }
169        }
170        None
171    }
172
173    /// Modifies the value of an attribute.
174    pub fn set_attr<S: Into<String>, V: IntoAttributeValue>(&mut self, name: S, val: V) {
175        let name = name.into();
176        let val = val.into_attribute_value();
177        for attr in &mut self.attributes {
178            if attr.name == name {
179                attr.value = val.expect("removing existing value via set_attr, this is not yet supported (TODO)"); // TODO
180                return;
181            }
182        }
183        if let Some(val) = val {
184            self.attributes.push(Attribute::new(name, val));
185        }
186    }
187
188    /// Returns whether the element has the given name and namespace.
189    ///
190    /// # Examples
191    ///
192    /// ```
193    /// use minidom::Element;
194    ///
195    /// let elem = Element::builder("name").ns("namespace").build();
196    ///
197    /// assert_eq!(elem.is("name", "namespace"), true);
198    /// assert_eq!(elem.is("name", "wrong"), false);
199    /// assert_eq!(elem.is("wrong", "namespace"), false);
200    /// assert_eq!(elem.is("wrong", "wrong"), false);
201    /// ```
202    pub fn is<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
203        let ns = self.namespace.as_ref().map(String::as_ref);
204        self.name == name.as_ref() && ns == Some(namespace.as_ref())
205    }
206
207    /// Parse a document from an `EventReader`.
208    pub fn from_reader<R: Read>(reader: &mut EventReader<R>) -> Result<Element, Error> {
209        loop {
210            let e = reader.next()?;
211            match e {
212                ReaderEvent::StartElement { name, attributes, namespace } => {
213                    let attributes = attributes.into_iter()
214                                               .map(|o| Attribute::new(o.name.local_name, o.value))
215                                               .collect();
216                    let ns = if let Some(ref prefix) = name.prefix {
217                        namespace.get(prefix)
218                    }
219                    else {
220                        namespace.get(NS_NO_PREFIX)
221                    }.map(|s| s.to_owned());
222                    let mut root = Element::new(name.local_name, ns, attributes, Vec::new());
223                    root.from_reader_inner(reader)?;
224                    return Ok(root);
225                },
226                ReaderEvent::EndDocument => {
227                    return Err(Error::EndOfDocument);
228                },
229                _ => () // TODO: may need more errors
230            }
231        }
232    }
233
234    fn from_reader_inner<R: Read>(&mut self, reader: &mut EventReader<R>) -> Result<(), Error> {
235        loop {
236            let e = reader.next()?;
237            match e {
238                ReaderEvent::StartElement { name, attributes, namespace } => {
239                    let attributes = attributes.into_iter()
240                                               .map(|o| Attribute::new(o.name.local_name, o.value))
241                                               .collect();
242                    let ns = if let Some(ref prefix) = name.prefix {
243                        namespace.get(prefix)
244                    }
245                    else {
246                        namespace.get(NS_NO_PREFIX)
247                    }.map(|s| s.to_owned());
248                    let elem = Element::new(name.local_name, ns, attributes, Vec::with_capacity(1));
249                    let elem_ref = self.append_child(elem);
250                    elem_ref.from_reader_inner(reader)?;
251                },
252                ReaderEvent::EndElement { .. } => {
253                    // TODO: may want to check whether we're closing the correct element
254                    return Ok(());
255                },
256                ReaderEvent::Characters(s) => {
257                    self.append_text_node(s);
258                },
259                ReaderEvent::CData(s) => {
260                    self.append_text_node(s);
261                },
262                ReaderEvent::EndDocument => {
263                    return Err(Error::EndOfDocument);
264                },
265                _ => (), // TODO: may need to implement more
266            }
267        }
268    }
269
270    /// Output a document to an `EventWriter`.
271    pub fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), Error> {
272        let name = if let Some(ref ns) = self.namespace {
273            Name::qualified(&self.name, &ns, None)
274        }
275        else {
276            Name::local(&self.name)
277        };
278        let mut start = WriterEvent::start_element(name);
279        if let Some(ref ns) = self.namespace {
280            start = start.default_ns(ns.as_ref());
281        }
282        for attr in &self.attributes { // TODO: I think this could be done a lot more efficiently
283            start = start.attr(Name::local(&attr.name), &attr.value);
284        }
285        writer.write(start)?;
286        for child in &self.children {
287            match *child {
288                Node::Element(ref e) => {
289                    e.write_to(writer)?;
290                },
291                Node::Text(ref s) => {
292                    writer.write(WriterEvent::characters(s))?;
293                },
294            }
295        }
296        writer.write(WriterEvent::end_element())?;
297        Ok(())
298    }
299
300    /// Returns an iterator over references to the children of this element.
301    ///
302    /// # Examples
303    ///
304    /// ```
305    /// use minidom::Element;
306    ///
307    /// let elem: Element = "<root><child1 /><child2 /><child3 /></root>".parse().unwrap();
308    ///
309    /// let mut iter = elem.children();
310    /// assert_eq!(iter.next().unwrap().name(), "child1");
311    /// assert_eq!(iter.next().unwrap().name(), "child2");
312    /// assert_eq!(iter.next().unwrap().name(), "child3");
313    /// assert_eq!(iter.next(), None);
314    /// ```
315    pub fn children<'a>(&'a self) -> Children<'a> {
316        Children {
317            iter: self.children.iter(),
318        }
319    }
320
321    /// Returns an iterator over mutable references to the children of this element.
322    pub fn children_mut<'a>(&'a mut self) -> ChildrenMut<'a> {
323        ChildrenMut {
324            iter: self.children.iter_mut(),
325        }
326    }
327
328    fn propagate_namespaces(&mut self) {
329        let ns = self.namespace.clone();
330        for child in self.children_mut() {
331            if child.namespace.is_none() {
332                child.namespace = ns.clone();
333                child.propagate_namespaces();
334            }
335        }
336    }
337
338    /// Appends a child node to the `Element`, returning the appended node.
339    ///
340    /// # Examples
341    ///
342    /// ```
343    /// use minidom::Element;
344    ///
345    /// let mut elem = Element::bare("root");
346    ///
347    /// assert_eq!(elem.children().count(), 0);
348    ///
349    /// elem.append_child(Element::bare("child"));
350    ///
351    /// {
352    ///     let mut iter = elem.children();
353    ///     assert_eq!(iter.next().unwrap().name(), "child");
354    ///     assert_eq!(iter.next(), None);
355    /// }
356    ///
357    /// let child = elem.append_child(Element::bare("new"));
358    ///
359    /// assert_eq!(child.name(), "new");
360    /// ```
361    pub fn append_child(&mut self, mut child: Element) -> &mut Element {
362        if child.namespace.is_none() && self.namespace.is_some() {
363            child.namespace = self.namespace.clone();
364            child.propagate_namespaces();
365        }
366        self.children.push(Node::Element(child));
367        if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
368            cld
369        }
370        else {
371            unreachable!()
372        }
373    }
374
375    /// Appends a text node to an `Element`.
376    ///
377    /// # Examples
378    ///
379    /// ```
380    /// use minidom::Element;
381    ///
382    /// let mut elem = Element::bare("node");
383    ///
384    /// assert_eq!(elem.text(), "");
385    ///
386    /// elem.append_text_node("text");
387    ///
388    /// assert_eq!(elem.text(), "text");
389    /// ```
390    pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
391        self.children.push(Node::Text(child.into()));
392    }
393
394    /// Appends a node to an `Element`.
395    ///
396    /// # Examples
397    ///
398    /// ```
399    /// use minidom::{Element, Node};
400    ///
401    /// let mut elem = Element::bare("node");
402    ///
403    /// elem.append_node(Node::Text("hello".to_owned()));
404    ///
405    /// assert_eq!(elem.text(), "hello");
406    /// ```
407    pub fn append_node(&mut self, node: Node) {
408        self.children.push(node);
409    }
410
411    /// Returns the concatenation of all text nodes in the `Element`.
412    ///
413    /// # Examples
414    ///
415    /// ```
416    /// use minidom::Element;
417    ///
418    /// let elem: Element = "<node>hello, world!</node>".parse().unwrap();
419    ///
420    /// assert_eq!(elem.text(), "hello, world!");
421    /// ```
422    pub fn text(&self) -> String {
423        let mut ret = String::new();
424        for fork in &self.children {
425            if let Node::Text(ref s) = *fork {
426                ret += s;
427            }
428        }
429        ret
430    }
431
432    /// Returns a reference to the first child element with the specific name and namespace, if it
433    /// exists in the direct descendants of this `Element`, else returns `None`.
434    ///
435    /// # Examples
436    ///
437    /// ```
438    /// use minidom::Element;
439    ///
440    /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
441    ///
442    /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
443    /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
444    /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
445    /// assert_eq!(elem.get_child("c", "ns"), None);
446    /// assert_eq!(elem.get_child("b", "other_ns"), None);
447    /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
448    /// ```
449    pub fn get_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> Option<&Element> {
450        for fork in &self.children {
451            if let Node::Element(ref e) = *fork {
452                if e.is(name.as_ref(), namespace.as_ref()) {
453                    return Some(e);
454                }
455            }
456        }
457        None
458    }
459
460    /// Returns a mutable reference to the first child element with the specific name and namespace,
461    /// if it exists in the direct descendants of this `Element`, else returns `None`.
462    pub fn get_child_mut<N: AsRef<str>, NS: AsRef<str>>(&mut self, name: N, namespace: NS) -> Option<&mut Element> {
463        for fork in &mut self.children {
464            if let Node::Element(ref mut e) = *fork {
465                if e.is(name.as_ref(), namespace.as_ref()) {
466                    return Some(e);
467                }
468            }
469        }
470        None
471    }
472
473    /// Returns whether a specific child with this name and namespace exists in the direct
474    /// descendants of the `Element`.
475    ///
476    /// # Examples
477    ///
478    /// ```
479    /// use minidom::Element;
480    ///
481    /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
482    ///
483    /// assert_eq!(elem.has_child("a", "other_ns"), true);
484    /// assert_eq!(elem.has_child("a", "ns"), true);
485    /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
486    /// assert_eq!(elem.has_child("b", "ns"), true);
487    /// assert_eq!(elem.has_child("b", "other_ns"), false);
488    /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
489    /// ```
490    pub fn has_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
491        self.get_child(name, namespace).is_some()
492    }
493}
494
495/// An iterator over references to children of an `Element`.
496pub struct Children<'a> {
497    iter: slice::Iter<'a, Node>,
498}
499
500impl<'a> Iterator for Children<'a> {
501    type Item = &'a Element;
502
503    fn next(&mut self) -> Option<&'a Element> {
504        while let Some(item) = self.iter.next() {
505            if let Node::Element(ref child) = *item {
506                return Some(child);
507            }
508        }
509        None
510    }
511}
512
513/// An iterator over mutable references to children of an `Element`.
514pub struct ChildrenMut<'a> {
515    iter: slice::IterMut<'a, Node>,
516}
517
518impl<'a> Iterator for ChildrenMut<'a> {
519    type Item = &'a mut Element;
520
521    fn next(&mut self) -> Option<&'a mut Element> {
522        while let Some(item) = self.iter.next() {
523            if let Node::Element(ref mut child) = *item {
524                return Some(child);
525            }
526        }
527        None
528    }
529}
530
531/// A builder for `Element`s.
532pub struct ElementBuilder {
533    root: Element,
534}
535
536impl ElementBuilder {
537    /// Sets the namespace.
538    pub fn ns<S: Into<String>>(mut self, namespace: S) -> ElementBuilder {
539        self.root.namespace = Some(namespace.into());
540        self
541    }
542
543    /// Sets an attribute.
544    pub fn attr<S: Into<String>, V: IntoAttributeValue>(mut self, name: S, value: V) -> ElementBuilder {
545        self.root.set_attr(name, value);
546        self
547    }
548
549    /// Appends anything implementing `IntoElements` into the tree.
550    pub fn append<T: IntoElements>(mut self, into: T) -> ElementBuilder {
551        {
552            let mut emitter = ElementEmitter::new(&mut self.root);
553            into.into_elements(&mut emitter);
554        }
555        self
556    }
557
558    /// Builds the `Element`.
559    pub fn build(self) -> Element {
560        self.root
561    }
562}
563
564#[test]
565fn test_element_new() {
566    let elem = Element::new( "name".to_owned()
567                           , Some("namespace".to_owned())
568                           , vec![ Attribute::new("name", "value") ]
569                           , Vec::new() );
570
571    assert_eq!(elem.name(), "name");
572    assert_eq!(elem.ns(), Some("namespace"));
573    assert_eq!(elem.attr("name"), Some("value"));
574    assert_eq!(elem.attr("inexistent"), None);
575}