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