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