lib.rs

  1extern crate xml;
  2
  3pub mod error;
  4pub mod attribute;
  5
  6use std::io::prelude::*;
  7
  8use std::convert::{From, 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            namespace: None,
 80            attributes: Vec::new(),
 81        }
 82    }
 83
 84    pub fn name(&self) -> &str {
 85        &self.name
 86    }
 87
 88    pub fn ns(&self) -> Option<&str> {
 89        self.namespace.as_ref()
 90                      .map(String::as_ref)
 91    }
 92
 93    pub fn attr(&self, name: &str) -> Option<&str> {
 94        for attr in &self.attributes {
 95            if attr.name == name {
 96                return Some(&attr.value);
 97            }
 98        }
 99        None
100    }
101
102    pub fn is<N: AsRef<str>, NS: AsRef<str>>(&self, name: N, namespace: NS) -> bool {
103        let ns = self.namespace.as_ref().map(String::as_ref);
104        self.name == name.as_ref() && ns == Some(namespace.as_ref())
105    }
106
107    pub fn from_reader<R: Read>(reader: &mut EventReader<R>) -> Result<Element, Error> {
108        loop {
109            let e = reader.next()?;
110            match e {
111                ReaderEvent::StartElement { name, attributes, namespace } => {
112                    let attributes = attributes.into_iter()
113                                               .map(|o| Attribute::new(o.name.local_name, o.value))
114                                               .collect();
115                    let ns = if let Some(ref prefix) = name.prefix {
116                        namespace.get(prefix)
117                    }
118                    else {
119                        namespace.get(NS_NO_PREFIX)
120                    }.map(|s| s.to_owned());
121                    let mut root = Element::new(name.local_name, ns, attributes);
122                    root.from_reader_inner(reader);
123                    return Ok(root);
124                },
125                ReaderEvent::EndDocument => {
126                    return Err(Error::EndOfDocument);
127                },
128                _ => () // TODO: may need more errors
129            }
130        }
131    }
132
133    fn from_reader_inner<R: Read>(&mut self, reader: &mut EventReader<R>) -> Result<(), Error> {
134        loop {
135            let e = reader.next()?;
136            match e {
137                ReaderEvent::StartElement { name, attributes, namespace } => {
138                    let attributes = attributes.into_iter()
139                                               .map(|o| Attribute::new(o.name.local_name, o.value))
140                                               .collect();
141                    let ns = if let Some(ref prefix) = name.prefix {
142                        namespace.get(prefix)
143                    }
144                    else {
145                        namespace.get(NS_NO_PREFIX)
146                    }.map(|s| s.to_owned());
147                    let elem = Element::new(name.local_name, ns, attributes);
148                    let elem_ref = self.append_child(elem);
149                    elem_ref.from_reader_inner(reader);
150                },
151                ReaderEvent::EndElement { .. } => {
152                    // TODO: may want to check whether we're closing the correct element
153                    return Ok(());
154                },
155                ReaderEvent::Characters(s) => {
156                    self.append_text_node(s);
157                },
158                ReaderEvent::CData(s) => {
159                    self.append_text_node(s);
160                },
161                ReaderEvent::EndDocument => {
162                    return Err(Error::EndOfDocument);
163                },
164                _ => (), // TODO: may need to implement more
165            }
166        }
167    }
168
169    pub fn write_to<W: Write>(&self, writer: &mut EventWriter<W>) -> Result<(), Error> {
170        let name = if let Some(ref ns) = self.namespace {
171            Name::qualified(&self.name, &ns, None)
172        }
173        else {
174            Name::local(&self.name)
175        };
176        let mut start = WriterEvent::start_element(name);
177        if let Some(ref ns) = self.namespace {
178            start = start.default_ns(ns.as_ref());
179        }
180        for attr in &self.attributes { // TODO: I think this could be done a lot more efficiently
181            start = start.attr(Name::local(&attr.name), &attr.value);
182        }
183        writer.write(start)?;
184        for child in &self.children {
185            match *child {
186                Fork::Element(ref e) => {
187                    e.write_to(writer)?;
188                },
189                Fork::Text(ref s) => {
190                    writer.write(WriterEvent::characters(s))?;
191                },
192            }
193        }
194        writer.write(WriterEvent::end_element())?;
195        Ok(())
196    }
197
198    pub fn children<'a>(&'a self) -> Children<'a> {
199        Children {
200            iter: self.children.iter(),
201        }
202    }
203
204    pub fn children_mut<'a>(&'a mut self) -> ChildrenMut<'a> {
205        ChildrenMut {
206            iter: self.children.iter_mut(),
207        }
208    }
209
210    pub fn append_child(&mut self, mut child: Element) -> &mut Element {
211        if child.namespace.is_none() {
212            child.namespace = self.namespace.clone();
213        }
214        self.children.push(Fork::Element(child));
215        if let Fork::Element(ref mut cld) = *self.children.last_mut().unwrap() {
216            cld
217        }
218        else {
219            unreachable!()
220        }
221    }
222
223    pub fn append_text_node<S: Into<String>>(&mut self, child: S) {
224        self.children.push(Fork::Text(child.into()));
225    }
226
227    pub fn text(&self) -> &str {
228        unimplemented!()
229    }
230
231    pub fn get_child<'a, N: Into<Name<'a>>>(&self, name: N) -> Option<&Element> {
232        unimplemented!()
233    }
234
235    pub fn get_child_mut<'a, N: Into<Name<'a>>>(&mut self, name: N) -> Option<&mut Element> {
236        unimplemented!()
237    }
238
239    pub fn into_child<'a, N: Into<Name<'a>>>(self, name: N) -> Option<Element> {
240        unimplemented!()
241    }
242}
243
244pub struct Children<'a> {
245    iter: slice::Iter<'a, Fork>,
246}
247
248impl<'a> Iterator for Children<'a> {
249    type Item = &'a Element;
250
251    fn next(&mut self) -> Option<&'a Element> {
252        while let Some(item) = self.iter.next() {
253            if let Fork::Element(ref child) = *item {
254                return Some(child);
255            }
256        }
257        None
258    }
259}
260
261pub struct ChildrenMut<'a> {
262    iter: slice::IterMut<'a, Fork>,
263}
264
265impl<'a> Iterator for ChildrenMut<'a> {
266    type Item = &'a mut Element;
267
268    fn next(&mut self) -> Option<&'a mut Element> {
269        while let Some(item) = self.iter.next() {
270            if let Fork::Element(ref mut child) = *item {
271                return Some(child);
272            }
273        }
274        None
275    }
276}
277
278pub struct ElementBuilder {
279    name: String,
280    namespace: Option<String>,
281    attributes: Vec<Attribute>,
282}
283
284impl ElementBuilder {
285    pub fn ns<S: Into<String>>(mut self, namespace: S) -> ElementBuilder {
286        self.namespace = Some(namespace.into());
287        self
288    }
289
290    pub fn attr<S: Into<String>, V: Into<String>>(mut self, name: S, value: V) -> ElementBuilder {
291        self.attributes.push(Attribute::new(name, value));
292        self
293    }
294
295    pub fn build(self) -> Element {
296        Element::new(self.name, self.namespace, self.attributes)
297    }
298}
299
300#[cfg(test)]
301mod tests {
302    use super::*;
303
304    use xml::reader::EventReader;
305    use xml::writer::EventWriter;
306
307    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>"#;
308
309    fn build_test_tree() -> Element {
310        let mut root = Element::builder("root")
311                               .ns("root_ns")
312                               .attr("a", "b")
313                               .build();
314        root.append_text_node("meow");
315        let child = Element::builder("child")
316                            .attr("c", "d")
317                            .build();
318        root.append_child(child);
319        let other_child = Element::builder("child")
320                                  .ns("child_ns")
321                                  .attr("d", "e")
322                                  .build();
323        root.append_child(other_child);
324        root.append_text_node("nya");
325        root
326    }
327
328    #[test]
329    fn reader_works() {
330        use std::io::Cursor;
331        let mut reader = EventReader::new(Cursor::new(TEST_STRING));
332        assert_eq!(Element::from_reader(&mut reader).unwrap(), build_test_tree());
333    }
334
335    #[test]
336    fn writer_works() {
337        let root = build_test_tree();
338        let mut out = Vec::new();
339        {
340            let mut writer = EventWriter::new(&mut out);
341            root.write_to(&mut writer).unwrap();
342        }
343        assert_eq!(String::from_utf8(out).unwrap(), TEST_STRING);
344    }
345
346    #[test]
347    fn builder_works() {
348        let elem = Element::builder("a")
349                           .ns("b")
350                           .attr("c", "d")
351                           .build();
352        assert_eq!(elem.name(), "a");
353        assert_eq!(elem.ns(), Some("b"));
354        assert_eq!(elem.attr("c"), Some("d"));
355        assert_eq!(elem.is("a", "b"), true);
356    }
357
358    #[test]
359    fn children_iter_works() {
360        let root = build_test_tree();
361        let mut iter = root.children();
362        assert!(iter.next().unwrap().is("child", "root_ns"));
363        assert!(iter.next().unwrap().is("child", "child_ns"));
364        assert_eq!(iter.next(), None);
365    }
366}