nv_xml/
xml_parser.rs

1use {XmlElement, XmlElementBuilder};
2
3use xml::reader::{XmlEvent, EventReader};
4
5use std::io::BufReader;
6
7#[derive(Debug, PartialEq)]
8pub enum ParseError
9{
10    MalformedXml,
11}
12
13#[derive(Debug)]
14pub struct XmlParser;
15
16impl XmlParser
17{	
18    pub fn parse(data : &str) -> Result<XmlElement, ParseError>
19    {
20        let reader = BufReader::new(data.as_bytes());
21        let mut builders = Vec::<XmlElementBuilder>::new();
22        for event in EventReader::new(reader).into_iter().filter_map(|e| e.ok())
23        {
24            if Self::is_start_event(&event)
25                {
26                    builders.push(XmlElementBuilder::new(event));
27                }
28            else if Self::is_data_event(&event)
29                {
30                    builders.last_mut().map(|b| b.add_data(event));
31
32                }
33            else if Self::is_end_event(&event)
34                {
35                    let finished_element_builder = builders.pop().unwrap();
36                    if builders.is_empty() // return last remaining element
37                        {return Ok(finished_element_builder.build())}
38                    else //pop parent from queue and add this element
39                        {
40                            let mut parent = builders.last_mut().unwrap();
41                            parent.add_child(finished_element_builder);}
42                        }
43        }
44        Err(ParseError::MalformedXml)
45    }
46
47	fn is_start_event(event : &XmlEvent) -> bool
48    {
49        match event
50        {
51            &XmlEvent::StartElement{..} => true,
52            _                           => false
53        }
54    }
55
56    fn is_end_event(event : &XmlEvent) -> bool
57    {
58        match event
59        {
60            &XmlEvent::EndElement{..} => true,
61            _                         => false
62        }
63    }    
64
65    fn is_data_event(event: &XmlEvent) -> bool
66    {
67        match event
68        {
69            &XmlEvent::Characters(_) => true,
70            _                        => false
71        }
72    }
73}
74
75#[cfg(test)]
76mod xml_parser_tests
77{
78    use super::*;
79
80    #[test]
81    fn correct_number_of_elements_test() -> ()
82    {
83        let data = "<data/>";
84        let element = XmlParser::parse(data).unwrap();
85        assert_eq!(element.children().len(), 0);
86    }
87
88    #[test]
89    fn can_parse() -> ()
90    {
91        let data = "<data/>";
92        let element = XmlParser::parse(data).unwrap();
93        assert_eq!(element.name(), "data");
94    }
95
96    #[test]
97    fn can_parse_nesting() -> ()
98    {
99        let data = "<data><something/></data>";
100        let element = XmlParser::parse(data).unwrap();
101        assert_eq!(element.name(), "data");
102        assert_eq!(element.children_with_name("something").len(), 1);
103    }
104
105    #[test]
106    fn can_parse_loads_of_nesting() -> ()
107    {
108        let data = "<data><something/><something/><new_thing><something/></new_thing></data>";
109        let element = XmlParser::parse(data).unwrap();
110        assert_eq!(element.name(), "data");
111        assert_eq!(element.children_with_name("something").len(), 2);
112        let new_children = element.children_with_name("new_thing");
113        assert_eq!(new_children.len(), 1);
114        assert_eq!(new_children.first().unwrap().children_with_name("something").len(), 1);
115    }
116
117    #[test]
118    fn bad_xml_test() -> ()
119    {
120        let data = "<data>";
121        let element = XmlParser::parse(data);
122        assert_eq!(element.unwrap_err(), ParseError::MalformedXml);
123    }
124
125    #[test]
126    fn can_parse_content() -> ()
127    {
128        let data = "<data>something</data>";
129        let element = XmlParser::parse(data).unwrap();
130        assert_eq!(element.data().unwrap(), "something");
131    }
132}