xml/
element_builder.rs

1// RustyXML
2// Copyright 2013-2016 RustyXML developers
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10use super::{Element, EndTag, Event, StartTag, Xml};
11use crate::parser::ParserError;
12use std::collections::HashMap;
13use std::error::Error;
14use std::fmt;
15
16#[derive(PartialEq, Debug, Clone)]
17/// The structure returned for errors encountered while building an `Element`
18pub enum BuilderError {
19    /// Errors encountered by the `Parser`
20    Parser(ParserError),
21    /// Elements were improperly nested, e.g. <a><b></a></b>
22    ImproperNesting,
23    /// No element was found
24    NoElement,
25}
26
27impl Error for BuilderError {
28    fn description(&self) -> &str {
29        match *self {
30            BuilderError::Parser(ref err) => err.description(),
31            BuilderError::ImproperNesting => "Elements not properly nested",
32            BuilderError::NoElement => "No elements found",
33        }
34    }
35
36    fn source(&self) -> Option<&(dyn Error + 'static)> {
37        match *self {
38            BuilderError::Parser(ref err) => Some(err),
39            _ => None,
40        }
41    }
42}
43
44impl fmt::Display for BuilderError {
45    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46        match *self {
47            BuilderError::Parser(ref err) => err.fmt(f),
48            BuilderError::ImproperNesting => write!(f, "Elements not properly nested"),
49            BuilderError::NoElement => write!(f, "No elements found"),
50        }
51    }
52}
53
54impl From<ParserError> for BuilderError {
55    fn from(err: ParserError) -> BuilderError {
56        BuilderError::Parser(err)
57    }
58}
59
60/// An Element Builder, building `Element`s from `Event`s as produced by `Parser`
61///
62/// ~~~
63/// use xml::{Parser, ElementBuilder};
64///
65/// let mut parser = Parser::new();
66/// let mut builder = ElementBuilder::new();
67///
68/// parser.feed_str("<example/>");
69/// for result in parser.filter_map(|event| builder.handle_event(event)) {
70///     println!("{}", result.unwrap());
71/// }
72/// ~~~
73pub struct ElementBuilder {
74    stack: Vec<Element>,
75    default_ns: Vec<Option<String>>,
76    prefixes: HashMap<String, String>,
77}
78
79impl ElementBuilder {
80    /// Returns a new `ElementBuilder`
81    pub fn new() -> ElementBuilder {
82        let mut prefixes = HashMap::with_capacity(2);
83        prefixes.insert(
84            "http://www.w3.org/XML/1998/namespace".to_owned(),
85            "xml".to_owned(),
86        );
87        prefixes.insert(
88            "http://www.w3.org/2000/xmlns/".to_owned(),
89            "xmlns".to_owned(),
90        );
91        ElementBuilder {
92            stack: Vec::new(),
93            default_ns: Vec::new(),
94            prefixes,
95        }
96    }
97
98    /// Bind a prefix to a namespace
99    pub fn define_prefix(&mut self, prefix: String, ns: String) {
100        self.prefixes.insert(ns, prefix);
101    }
102
103    /// Set the default namespace
104    pub fn set_default_ns(&mut self, ns: String) {
105        self.default_ns = vec![Some(ns)];
106    }
107
108    /// Let the builder process an `Event` to ultimately build an `Element`.
109    ///
110    /// While no root element has been finished `None` is returned.
111    /// Once sufficent data has been received an `Element` is returned as `Some(Ok(elem))`.
112    /// Upon Error `Some(Err("message"))` is returned.
113    pub fn handle_event(
114        &mut self,
115        e: Result<Event, ParserError>,
116    ) -> Option<Result<Element, BuilderError>> {
117        let e = match e {
118            Ok(o) => o,
119            Err(e) => return Some(Err(From::from(e))),
120        };
121        match e {
122            Event::PI(cont) => {
123                if let Some(elem) = self.stack.last_mut() {
124                    elem.children.push(Xml::PINode(cont));
125                }
126            }
127            Event::ElementStart(StartTag {
128                name,
129                ns,
130                prefix: _,
131                attributes,
132            }) => {
133                let mut elem = Element {
134                    name,
135                    ns,
136                    default_ns: None,
137                    prefixes: self.prefixes.clone(),
138                    attributes,
139                    children: Vec::new(),
140                };
141
142                if let Some(default) = self.default_ns.last().cloned() {
143                    self.default_ns.push(default)
144                }
145
146                for (&(ref name, ref ns), value) in &elem.attributes {
147                    if ns.is_none() && name == "xmlns" {
148                        self.default_ns.pop();
149                        if value.is_empty() {
150                            self.default_ns.push(None);
151                        } else {
152                            self.default_ns.push(Some(value.clone()));
153                        }
154                        continue;
155                    }
156
157                    if ns
158                        .as_ref()
159                        .map_or(false, |x| x == "http://www.w3.org/2000/xmlns/")
160                    {
161                        elem.prefixes.insert(value.clone(), name.clone());
162                    }
163                }
164                elem.default_ns = self.default_ns.last().unwrap_or(&None).clone();
165
166                self.stack.push(elem);
167            }
168            Event::ElementEnd(EndTag {
169                name,
170                ns,
171                prefix: _,
172            }) => {
173                let elem = match self.stack.pop() {
174                    Some(elem) => elem,
175                    None => return Some(Err(BuilderError::ImproperNesting)),
176                };
177                self.default_ns.pop();
178                if elem.name != name || elem.ns != ns {
179                    return Some(Err(BuilderError::ImproperNesting));
180                } else {
181                    match self.stack.last_mut() {
182                        Some(e) => e.children.push(Xml::ElementNode(elem)),
183                        None => return Some(Ok(elem)),
184                    }
185                }
186            }
187            Event::Characters(chars) => {
188                if let Some(elem) = self.stack.last_mut() {
189                    elem.children.push(Xml::CharacterNode(chars));
190                }
191            }
192            Event::CDATA(chars) => {
193                if let Some(elem) = self.stack.last_mut() {
194                    elem.children.push(Xml::CDATANode(chars));
195                }
196            }
197            Event::Comment(cont) => {
198                if let Some(elem) = self.stack.last_mut() {
199                    elem.children.push(Xml::CommentNode(cont));
200                }
201            }
202        }
203        None
204    }
205}