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| {
215                                                    Attribute::new(
216                                                        match o.name.prefix {
217                                                            Some(prefix) => format!("{}:{}", prefix, o.name.local_name),
218                                                            None => o.name.local_name
219                                                        },
220                                                        o.value
221                                                    )
222                                                })
223                                               .collect();
224                    let ns = if let Some(ref prefix) = name.prefix {
225                        namespace.get(prefix)
226                    }
227                    else {
228                        namespace.get(NS_NO_PREFIX)
229                    }.map(|s| s.to_owned());
230
231                    let mut root = Element::new(name.local_name, ns, attributes, Vec::new());
232                    root.from_reader_inner(reader)?;
233                    return Ok(root);
234                },
235                ReaderEvent::EndDocument => {
236                    return Err(Error::EndOfDocument);
237                },
238                _ => () // TODO: may need more errors
239            }
240        }
241    }
242
243    fn from_reader_inner<R: Read>(&mut self, reader: &mut EventReader<R>) -> Result<(), Error> {
244        loop {
245            let e = reader.next()?;
246            match e {
247                ReaderEvent::StartElement { name, attributes, namespace } => {
248                    let attributes = attributes.into_iter()
249                                               .map(|o| {
250                                                    Attribute::new(
251                                                        match o.name.prefix {
252                                                            Some(prefix) => format!("{}:{}", prefix, o.name.local_name),
253                                                            None => o.name.local_name
254                                                        },
255                                                        o.value
256                                                    )
257                                                })
258                                               .collect();
259                    let ns = if let Some(ref prefix) = name.prefix {
260                        namespace.get(prefix)
261                    }
262                    else {
263                        namespace.get(NS_NO_PREFIX)
264                    }.map(|s| s.to_owned());
265                    let elem = Element::new(name.local_name, ns, attributes, Vec::with_capacity(1));
266                    let elem_ref = self.append_child(elem);
267                    elem_ref.from_reader_inner(reader)?;
268                },
269                ReaderEvent::EndElement { .. } => {
270                    // TODO: may want to check whether we're closing the correct element
271                    return Ok(());
272                },
273                ReaderEvent::Characters(s) => {
274                    self.append_text_node(s);
275                },
276                ReaderEvent::CData(s) => {
277                    self.append_text_node(s);
278                },
279                ReaderEvent::EndDocument => {
280                    return Err(Error::EndOfDocument);
281                },
282                _ => (), // TODO: may need to implement more
283            }
284        }
285    }
286
287    /// Output a document to an `EventWriter`.
288    pub fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), Error> {
289        let name = if let Some(ref ns) = self.namespace {
290            Name::qualified(&self.name, &ns, None)
291        }
292        else {
293            Name::local(&self.name)
294        };
295        let mut start = WriterEvent::start_element(name);
296        if let Some(ref ns) = self.namespace {
297            start = start.default_ns(ns.as_ref());
298        }
299        for attr in &self.attributes { // TODO: I think this could be done a lot more efficiently
300            start = start.attr(Name::local(&attr.name), &attr.value);
301        }
302        writer.write(start)?;
303        for child in &self.children {
304            match *child {
305                Node::Element(ref e) => {
306                    e.write_to(writer)?;
307                },
308                Node::Text(ref s) => {
309                    writer.write(WriterEvent::characters(s))?;
310                },
311            }
312        }
313        writer.write(WriterEvent::end_element())?;
314        Ok(())
315    }
316
317    /// Returns an iterator over references to the children of this element.
318    ///
319    /// # Examples
320    ///
321    /// ```
322    /// use minidom::Element;
323    ///
324    /// let elem: Element = "<root><child1 /><child2 /><child3 /></root>".parse().unwrap();
325    ///
326    /// let mut iter = elem.children();
327    /// assert_eq!(iter.next().unwrap().name(), "child1");
328    /// assert_eq!(iter.next().unwrap().name(), "child2");
329    /// assert_eq!(iter.next().unwrap().name(), "child3");
330    /// assert_eq!(iter.next(), None);
331    /// ```
332    pub fn children<'a>(&'a self) -> Children<'a> {
333        Children {
334            iter: self.children.iter(),
335        }
336    }
337
338    /// Returns an iterator over mutable references to the children of this element.
339    pub fn children_mut<'a>(&'a mut self) -> ChildrenMut<'a> {
340        ChildrenMut {
341            iter: self.children.iter_mut(),
342        }
343    }
344
345    fn propagate_namespaces(&mut self) {
346        let ns = self.namespace.clone();
347        for child in self.children_mut() {
348            if child.namespace.is_none() {
349                child.namespace = ns.clone();
350                child.propagate_namespaces();
351            }
352        }
353    }
354
355    /// Appends a child node to the `Element`, returning the appended node.
356    ///
357    /// # Examples
358    ///
359    /// ```
360    /// use minidom::Element;
361    ///
362    /// let mut elem = Element::bare("root");
363    ///
364    /// assert_eq!(elem.children().count(), 0);
365    ///
366    /// elem.append_child(Element::bare("child"));
367    ///
368    /// {
369    ///     let mut iter = elem.children();
370    ///     assert_eq!(iter.next().unwrap().name(), "child");
371    ///     assert_eq!(iter.next(), None);
372    /// }
373    ///
374    /// let child = elem.append_child(Element::bare("new"));
375    ///
376    /// assert_eq!(child.name(), "new");
377    /// ```
378    pub fn append_child(&mut self, mut child: Element) -> &mut Element {
379        if child.namespace.is_none() && self.namespace.is_some() {
380            child.namespace = self.namespace.clone();
381            child.propagate_namespaces();
382        }
383        self.children.push(Node::Element(child));
384        if let Node::Element(ref mut cld) = *self.children.last_mut().unwrap() {
385            cld
386        }
387        else {
388            unreachable!()
389        }
390    }
391
392    /// Appends a text node to an `Element`.
393    ///
394    /// # Examples
395    ///
396    /// ```
397    /// use minidom::Element;
398    ///
399    /// let mut elem = Element::bare("node");
400    ///
401    /// assert_eq!(elem.text(), "");
402    ///
403    /// elem.append_text_node("text");
404    ///
405    /// assert_eq!(elem.text(), "text");
406    /// ```
407    pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
408        self.children.push(Node::Text(child.into()));
409    }
410
411    /// Appends a node to an `Element`.
412    ///
413    /// # Examples
414    ///
415    /// ```
416    /// use minidom::{Element, Node};
417    ///
418    /// let mut elem = Element::bare("node");
419    ///
420    /// elem.append_node(Node::Text("hello".to_owned()));
421    ///
422    /// assert_eq!(elem.text(), "hello");
423    /// ```
424    pub fn append_node(&mut self, node: Node) {
425        self.children.push(node);
426    }
427
428    /// Returns the concatenation of all text nodes in the `Element`.
429    ///
430    /// # Examples
431    ///
432    /// ```
433    /// use minidom::Element;
434    ///
435    /// let elem: Element = "<node>hello, world!</node>".parse().unwrap();
436    ///
437    /// assert_eq!(elem.text(), "hello, world!");
438    /// ```
439    pub fn text(&self) -> String {
440        let mut ret = String::new();
441        for fork in &self.children {
442            if let Node::Text(ref s) = *fork {
443                ret += s;
444            }
445        }
446        ret
447    }
448
449    /// Returns a reference to the first child element with the specific name and namespace, if it
450    /// exists in the direct descendants of this `Element`, else returns `None`.
451    ///
452    /// # Examples
453    ///
454    /// ```
455    /// use minidom::Element;
456    ///
457    /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
458    ///
459    /// assert!(elem.get_child("a", "ns").unwrap().is("a", "ns"));
460    /// assert!(elem.get_child("a", "other_ns").unwrap().is("a", "other_ns"));
461    /// assert!(elem.get_child("b", "ns").unwrap().is("b", "ns"));
462    /// assert_eq!(elem.get_child("c", "ns"), None);
463    /// assert_eq!(elem.get_child("b", "other_ns"), None);
464    /// assert_eq!(elem.get_child("a", "inexistent_ns"), None);
465    /// ```
466    pub fn get_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> Option<&Element> {
467        for fork in &self.children {
468            if let Node::Element(ref e) = *fork {
469                if e.is(name.as_ref(), namespace.as_ref()) {
470                    return Some(e);
471                }
472            }
473        }
474        None
475    }
476
477    /// Returns a mutable reference to the first child element with the specific name and namespace,
478    /// if it exists in the direct descendants of this `Element`, else returns `None`.
479    pub fn get_child_mut<N: AsRef<str>, NS: AsRef<str>>(&mut self, name: N, namespace: NS) -> Option<&mut Element> {
480        for fork in &mut self.children {
481            if let Node::Element(ref mut e) = *fork {
482                if e.is(name.as_ref(), namespace.as_ref()) {
483                    return Some(e);
484                }
485            }
486        }
487        None
488    }
489
490    /// Returns whether a specific child with this name and namespace exists in the direct
491    /// descendants of the `Element`.
492    ///
493    /// # Examples
494    ///
495    /// ```
496    /// use minidom::Element;
497    ///
498    /// let elem: Element = r#"<node xmlns="ns"><a /><a xmlns="other_ns" /><b /></node>"#.parse().unwrap();
499    ///
500    /// assert_eq!(elem.has_child("a", "other_ns"), true);
501    /// assert_eq!(elem.has_child("a", "ns"), true);
502    /// assert_eq!(elem.has_child("a", "inexistent_ns"), false);
503    /// assert_eq!(elem.has_child("b", "ns"), true);
504    /// assert_eq!(elem.has_child("b", "other_ns"), false);
505    /// assert_eq!(elem.has_child("b", "inexistent_ns"), false);
506    /// ```
507    pub fn has_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
508        self.get_child(name, namespace).is_some()
509    }
510}
511
512/// An iterator over references to children of an `Element`.
513pub struct Children<'a> {
514    iter: slice::Iter<'a, Node>,
515}
516
517impl<'a> Iterator for Children<'a> {
518    type Item = &'a Element;
519
520    fn next(&mut self) -> Option<&'a Element> {
521        while let Some(item) = self.iter.next() {
522            if let Node::Element(ref child) = *item {
523                return Some(child);
524            }
525        }
526        None
527    }
528}
529
530/// An iterator over mutable references to children of an `Element`.
531pub struct ChildrenMut<'a> {
532    iter: slice::IterMut<'a, Node>,
533}
534
535impl<'a> Iterator for ChildrenMut<'a> {
536    type Item = &'a mut Element;
537
538    fn next(&mut self) -> Option<&'a mut Element> {
539        while let Some(item) = self.iter.next() {
540            if let Node::Element(ref mut child) = *item {
541                return Some(child);
542            }
543        }
544        None
545    }
546}
547
548/// A builder for `Element`s.
549pub struct ElementBuilder {
550    root: Element,
551}
552
553impl ElementBuilder {
554    /// Sets the namespace.
555    pub fn ns<S: Into<String>>(mut self, namespace: S) -> ElementBuilder {
556        self.root.namespace = Some(namespace.into());
557        self
558    }
559
560    /// Sets an attribute.
561    pub fn attr<S: Into<String>, V: IntoAttributeValue>(mut self, name: S, value: V) -> ElementBuilder {
562        self.root.set_attr(name, value);
563        self
564    }
565
566    /// Appends anything implementing `IntoElements` into the tree.
567    pub fn append<T: IntoElements>(mut self, into: T) -> ElementBuilder {
568        {
569            let mut emitter = ElementEmitter::new(&mut self.root);
570            into.into_elements(&mut emitter);
571        }
572        self
573    }
574
575    /// Builds the `Element`.
576    pub fn build(self) -> Element {
577        self.root
578    }
579}
580
581#[test]
582fn test_element_new() {
583    let elem = Element::new( "name".to_owned()
584                           , Some("namespace".to_owned())
585                           , vec![ Attribute::new("name", "value") ]
586                           , Vec::new() );
587
588    assert_eq!(elem.name(), "name");
589    assert_eq!(elem.ns(), Some("namespace"));
590    assert_eq!(elem.attr("name"), Some("value"));
591    assert_eq!(elem.attr("inexistent"), None);
592}