lib.rs

  1extern crate xml;
  2
  3pub mod error;
  4pub mod attribute;
  5
  6use std::io::prelude::*;
  7
  8use std::convert::AsRef;
  9
 10use std::iter::Iterator;
 11
 12use std::slice;
 13
 14use std::fmt;
 15
 16use xml::reader::{XmlEvent as ReaderEvent, EventReader};
 17use xml::writer::{XmlEvent as WriterEvent, EventWriter};
 18use xml::name::Name;
 19use xml::namespace::NS_NO_PREFIX;
 20
 21use error::Error;
 22
 23use attribute::Attribute;
 24
 25#[derive(Clone, PartialEq, Eq)]
 26pub struct Element {
 27    name: String,
 28    namespace: Option<String>,
 29    attributes: Vec<Attribute>,
 30    children: Vec<Fork>,
 31}
 32
 33impl fmt::Debug for Element {
 34    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 35        if let Some(ref ns) = self.namespace {
 36            write!(fmt, "<{{{}}}{}", ns, self.name)?;
 37        }
 38        else {
 39            write!(fmt, "<{}", self.name)?;
 40        }
 41        for attr in &self.attributes {
 42            write!(fmt, " {}", attr)?;
 43        }
 44        write!(fmt, ">")?;
 45        for child in &self.children {
 46            match *child {
 47                Fork::Element(ref e) => {
 48                    write!(fmt, "{:?}", e)?;
 49                },
 50                Fork::Text(ref s) => {
 51                    write!(fmt, "{}", s)?;
 52                },
 53            }
 54        }
 55        write!(fmt, "</{}>", self.name)?;
 56        Ok(())
 57    }
 58}
 59
 60#[derive(Clone, Debug, PartialEq, Eq)]
 61pub enum Fork {
 62    Element(Element),
 63    Text(String),
 64}
 65
 66impl Element {
 67    pub fn new(name: String, namespace: Option<String>, attributes: Vec<Attribute>) -> Element {
 68        Element {
 69            name: name,
 70            namespace: namespace,
 71            attributes: attributes,
 72            children: Vec::new(),
 73        }
 74    }
 75
 76    pub fn builder<S: Into<String>>(name: S) -> ElementBuilder {
 77        ElementBuilder {
 78            name: name.into(),
 79            text: None,
 80            namespace: None,
 81            attributes: Vec::new(),
 82        }
 83    }
 84
 85    pub fn name(&self) -> &str {
 86        &self.name
 87    }
 88
 89    pub fn ns(&self) -> Option<&str> {
 90        self.namespace.as_ref()
 91                      .map(String::as_ref)
 92    }
 93
 94    pub fn attr(&self, name: &str) -> Option<&str> {
 95        for attr in &self.attributes {
 96            if attr.name == name {
 97                return Some(&attr.value);
 98            }
 99        }
100        None
101    }
102
103    pub fn is<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
104        let ns = self.namespace.as_ref().map(String::as_ref);
105        self.name == name.as_ref() && ns == Some(namespace.as_ref())
106    }
107
108    pub fn from_reader<R: Read>(reader: &mut EventReader<R>) -> Result<Element, Error> {
109        loop {
110            let e = reader.next()?;
111            match e {
112                ReaderEvent::StartElement { name, attributes, namespace } => {
113                    let attributes = attributes.into_iter()
114                                               .map(|o| Attribute::new(o.name.local_name, o.value))
115                                               .collect();
116                    let ns = if let Some(ref prefix) = name.prefix {
117                        namespace.get(prefix)
118                    }
119                    else {
120                        namespace.get(NS_NO_PREFIX)
121                    }.map(|s| s.to_owned());
122                    let mut root = Element::new(name.local_name, ns, attributes);
123                    root.from_reader_inner(reader)?;
124                    return Ok(root);
125                },
126                ReaderEvent::EndDocument => {
127                    return Err(Error::EndOfDocument);
128                },
129                _ => () // TODO: may need more errors
130            }
131        }
132    }
133
134    fn from_reader_inner<R: Read>(&mut self, reader: &mut EventReader<R>) -> Result<(), Error> {
135        loop {
136            let e = reader.next()?;
137            match e {
138                ReaderEvent::StartElement { name, attributes, namespace } => {
139                    let attributes = attributes.into_iter()
140                                               .map(|o| Attribute::new(o.name.local_name, o.value))
141                                               .collect();
142                    let ns = if let Some(ref prefix) = name.prefix {
143                        namespace.get(prefix)
144                    }
145                    else {
146                        namespace.get(NS_NO_PREFIX)
147                    }.map(|s| s.to_owned());
148                    let elem = Element::new(name.local_name, ns, attributes);
149                    let elem_ref = self.append_child(elem);
150                    elem_ref.from_reader_inner(reader)?;
151                },
152                ReaderEvent::EndElement { .. } => {
153                    // TODO: may want to check whether we're closing the correct element
154                    return Ok(());
155                },
156                ReaderEvent::Characters(s) => {
157                    self.append_text_node(s);
158                },
159                ReaderEvent::CData(s) => {
160                    self.append_text_node(s);
161                },
162                ReaderEvent::EndDocument => {
163                    return Err(Error::EndOfDocument);
164                },
165                _ => (), // TODO: may need to implement more
166            }
167        }
168    }
169
170    pub fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), Error> {
171        let name = if let Some(ref ns) = self.namespace {
172            Name::qualified(&self.name, &ns, None)
173        }
174        else {
175            Name::local(&self.name)
176        };
177        let mut start = WriterEvent::start_element(name);
178        if let Some(ref ns) = self.namespace {
179            start = start.default_ns(ns.as_ref());
180        }
181        for attr in &self.attributes { // TODO: I think this could be done a lot more efficiently
182            start = start.attr(Name::local(&attr.name), &attr.value);
183        }
184        writer.write(start)?;
185        for child in &self.children {
186            match *child {
187                Fork::Element(ref e) => {
188                    e.write_to(writer)?;
189                },
190                Fork::Text(ref s) => {
191                    writer.write(WriterEvent::characters(s))?;
192                },
193            }
194        }
195        writer.write(WriterEvent::end_element())?;
196        Ok(())
197    }
198
199    pub fn children<'a>(&'a self) -> Children<'a> {
200        Children {
201            iter: self.children.iter(),
202        }
203    }
204
205    pub fn children_mut<'a>(&'a mut self) -> ChildrenMut<'a> {
206        ChildrenMut {
207            iter: self.children.iter_mut(),
208        }
209    }
210
211    pub fn append_child(&mut self, mut child: Element) -> &mut Element {
212        if child.namespace.is_none() {
213            child.namespace = self.namespace.clone();
214        }
215        self.children.push(Fork::Element(child));
216        if let Fork::Element(ref mut cld) = *self.children.last_mut().unwrap() {
217            cld
218        }
219        else {
220            unreachable!()
221        }
222    }
223
224    pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
225        self.children.push(Fork::Text(child.into()));
226    }
227
228    pub fn text(&self) -> String {
229        let mut ret = String::new();
230        for fork in &self.children {
231            if let Fork::Text(ref s) = *fork {
232                ret += s;
233            }
234        }
235        ret
236    }
237
238    pub fn get_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> Option<&Element> {
239        for fork in &self.children {
240            if let Fork::Element(ref e) = *fork {
241                if e.is(name.as_ref(), namespace.as_ref()) {
242                    return Some(e);
243                }
244            }
245        }
246        None
247    }
248
249    pub fn get_child_mut<N: AsRef<str>, NS: AsRef<str>>(&mut self, name: N, namespace: NS) -> Option<&mut Element> {
250        for fork in &mut self.children {
251            if let Fork::Element(ref mut e) = *fork {
252                if e.is(name.as_ref(), namespace.as_ref()) {
253                    return Some(e);
254                }
255            }
256        }
257        None
258    }
259
260    pub fn has_child<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
261        self.get_child(name, namespace).is_some()
262    }
263}
264
265pub struct Children<'a> {
266    iter: slice::Iter<'a, Fork>,
267}
268
269impl<'a> Iterator for Children<'a> {
270    type Item = &'a Element;
271
272    fn next(&mut self) -> Option<&'a Element> {
273        while let Some(item) = self.iter.next() {
274            if let Fork::Element(ref child) = *item {
275                return Some(child);
276            }
277        }
278        None
279    }
280}
281
282pub struct ChildrenMut<'a> {
283    iter: slice::IterMut<'a, Fork>,
284}
285
286impl<'a> Iterator for ChildrenMut<'a> {
287    type Item = &'a mut Element;
288
289    fn next(&mut self) -> Option<&'a mut Element> {
290        while let Some(item) = self.iter.next() {
291            if let Fork::Element(ref mut child) = *item {
292                return Some(child);
293            }
294        }
295        None
296    }
297}
298
299pub struct ElementBuilder {
300    name: String,
301    text: Option<String>,
302    namespace: Option<String>,
303    attributes: Vec<Attribute>,
304}
305
306impl ElementBuilder {
307    pub fn ns<S: Into<String>>(mut self, namespace: S) -> ElementBuilder {
308        self.namespace = Some(namespace.into());
309        self
310    }
311
312    pub fn attr<S: Into<String>, V: Into<String>>(mut self, name: S, value: V) -> ElementBuilder {
313        self.attributes.push(Attribute::new(name, value));
314        self
315    }
316
317    pub fn text<S: Into<String>>(mut self, text: S) -> ElementBuilder {
318        self.text = Some(text.into());
319        self
320    }
321
322    pub fn build(self) -> Element {
323        let mut elem = Element::new(self.name, self.namespace, self.attributes);
324        if let Some(text) = self.text {
325            elem.append_text_node(text);
326        }
327        elem
328    }
329}
330
331#[cfg(test)]
332mod tests {
333    use super::*;
334
335    use xml::reader::EventReader;
336    use xml::writer::EventWriter;
337
338    const TEST_STRING: &'static str = r#"<?xml version="1.0" encoding="utf-8"?><root xmlns="root_ns" a="b">meow<child c="d" /><child xmlns="child_ns" d="e" />nya</root>"#;
339
340    fn build_test_tree() -> Element {
341        let mut root = Element::builder("root")
342                               .ns("root_ns")
343                               .attr("a", "b")
344                               .build();
345        root.append_text_node("meow");
346        let child = Element::builder("child")
347                            .attr("c", "d")
348                            .build();
349        root.append_child(child);
350        let other_child = Element::builder("child")
351                                  .ns("child_ns")
352                                  .attr("d", "e")
353                                  .build();
354        root.append_child(other_child);
355        root.append_text_node("nya");
356        root
357    }
358
359    #[test]
360    fn reader_works() {
361        use std::io::Cursor;
362        let mut reader = EventReader::new(Cursor::new(TEST_STRING));
363        assert_eq!(Element::from_reader(&mut reader).unwrap(), build_test_tree());
364    }
365
366    #[test]
367    fn writer_works() {
368        let root = build_test_tree();
369        let mut out = Vec::new();
370        {
371            let mut writer = EventWriter::new(&mut out);
372            root.write_to(&mut writer).unwrap();
373        }
374        assert_eq!(String::from_utf8(out).unwrap(), TEST_STRING);
375    }
376
377    #[test]
378    fn builder_works() {
379        let elem = Element::builder("a")
380                           .ns("b")
381                           .attr("c", "d")
382                           .text("e")
383                           .build();
384        assert_eq!(elem.name(), "a");
385        assert_eq!(elem.ns(), Some("b"));
386        assert_eq!(elem.attr("c"), Some("d"));
387        assert_eq!(elem.attr("x"), None);
388        assert_eq!(elem.text(), "e");
389        assert!(elem.is("a", "b"));
390    }
391
392    #[test]
393    fn children_iter_works() {
394        let root = build_test_tree();
395        let mut iter = root.children();
396        assert!(iter.next().unwrap().is("child", "root_ns"));
397        assert!(iter.next().unwrap().is("child", "child_ns"));
398        assert_eq!(iter.next(), None);
399    }
400
401    #[test]
402    fn get_child_works() {
403        let root = build_test_tree();
404        assert_eq!(root.get_child("child", "inexistent_ns"), None);
405        assert_eq!(root.get_child("not_a_child", "root_ns"), None);
406        assert!(root.get_child("child", "root_ns").unwrap().is("child", "root_ns"));
407        assert!(root.get_child("child", "child_ns").unwrap().is("child", "child_ns"));
408        assert_eq!(root.get_child("child", "root_ns").unwrap().attr("c"), Some("d"));
409        assert_eq!(root.get_child("child", "child_ns").unwrap().attr("d"), Some("e"));
410    }
411}