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 crate::parser::ParserError;
11use crate::{Element, EndTag, Event, StartTag, Xml};
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 source(&self) -> Option<&(dyn Error + 'static)> {
29        match *self {
30            BuilderError::Parser(ref err) => Some(err),
31            _ => None,
32        }
33    }
34}
35
36impl fmt::Display for BuilderError {
37    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38        match *self {
39            BuilderError::Parser(ref err) => err.fmt(f),
40            BuilderError::ImproperNesting => write!(f, "Elements not properly nested"),
41            BuilderError::NoElement => write!(f, "No elements found"),
42        }
43    }
44}
45
46impl From<ParserError> for BuilderError {
47    fn from(err: ParserError) -> BuilderError {
48        BuilderError::Parser(err)
49    }
50}
51
52/// An Element Builder, building `Element`s from `Event`s as produced by `Parser`
53///
54/// ~~~
55/// use xml::{Parser, ElementBuilder};
56///
57/// let mut parser = Parser::new();
58/// let mut builder = ElementBuilder::new();
59///
60/// parser.feed_str("<example/>");
61/// for result in parser.filter_map(|event| builder.handle_event(event)) {
62///     println!("{}", result.unwrap());
63/// }
64/// ~~~
65pub struct ElementBuilder {
66    stack: Vec<Element>,
67    default_ns: Vec<Option<String>>,
68    prefixes: HashMap<String, String>,
69}
70
71impl ElementBuilder {
72    /// Returns a new `ElementBuilder`
73    pub fn new() -> ElementBuilder {
74        let mut prefixes = HashMap::with_capacity(2);
75        prefixes.insert(
76            "http://www.w3.org/XML/1998/namespace".to_owned(),
77            "xml".to_owned(),
78        );
79        prefixes.insert(
80            "http://www.w3.org/2000/xmlns/".to_owned(),
81            "xmlns".to_owned(),
82        );
83        ElementBuilder {
84            stack: Vec::new(),
85            default_ns: Vec::new(),
86            prefixes,
87        }
88    }
89
90    /// Bind a prefix to a namespace
91    pub fn define_prefix(&mut self, prefix: String, ns: String) {
92        self.prefixes.insert(ns, prefix);
93    }
94
95    /// Set the default namespace
96    pub fn set_default_ns(&mut self, ns: String) {
97        self.default_ns = vec![Some(ns)];
98    }
99
100    /// Let the builder process an `Event` to ultimately build an `Element`.
101    ///
102    /// While no root element has been finished `None` is returned.
103    /// Once sufficient data has been received an `Element` is returned as `Some(Ok(elem))`.
104    /// Upon Error `Some(Err("message"))` is returned.
105    pub fn handle_event(
106        &mut self,
107        e: Result<Event, ParserError>,
108    ) -> Option<Result<Element, BuilderError>> {
109        let e = match e {
110            Ok(o) => o,
111            Err(e) => return Some(Err(From::from(e))),
112        };
113        match e {
114            Event::PI(cont) => {
115                if let Some(elem) = self.stack.last_mut() {
116                    elem.children.push(Xml::PINode(cont));
117                }
118            }
119            Event::ElementStart(StartTag {
120                name,
121                ns,
122                prefix: _,
123                attributes,
124            }) => {
125                let mut elem = Element {
126                    name,
127                    ns,
128                    default_ns: None,
129                    prefixes: self.prefixes.clone(),
130                    attributes,
131                    children: Vec::new(),
132                };
133
134                if let Some(default) = self.default_ns.last().cloned() {
135                    self.default_ns.push(default)
136                }
137
138                for (&(ref name, ref ns), value) in &elem.attributes {
139                    if ns.is_none() && name == "xmlns" {
140                        self.default_ns.pop();
141                        if value.is_empty() {
142                            self.default_ns.push(None);
143                        } else {
144                            self.default_ns.push(Some(value.clone()));
145                        }
146                        continue;
147                    }
148
149                    if ns
150                        .as_ref()
151                        .map_or(false, |x| x == "http://www.w3.org/2000/xmlns/")
152                    {
153                        elem.prefixes.insert(value.clone(), name.clone());
154                    }
155                }
156                elem.default_ns = self.default_ns.last().unwrap_or(&None).clone();
157
158                self.stack.push(elem);
159            }
160            Event::ElementEnd(EndTag {
161                name,
162                ns,
163                prefix: _,
164            }) => {
165                let elem = match self.stack.pop() {
166                    Some(elem) => elem,
167                    None => return Some(Err(BuilderError::ImproperNesting)),
168                };
169                self.default_ns.pop();
170                if elem.name != name || elem.ns != ns {
171                    return Some(Err(BuilderError::ImproperNesting));
172                } else {
173                    match self.stack.last_mut() {
174                        Some(e) => e.children.push(Xml::ElementNode(elem)),
175                        None => return Some(Ok(elem)),
176                    }
177                }
178            }
179            Event::Characters(chars) => {
180                if let Some(elem) = self.stack.last_mut() {
181                    elem.children.push(Xml::CharacterNode(chars));
182                }
183            }
184            Event::CDATA(chars) => {
185                if let Some(elem) = self.stack.last_mut() {
186                    elem.children.push(Xml::CDATANode(chars));
187                }
188            }
189            Event::Comment(cont) => {
190                if let Some(elem) = self.stack.last_mut() {
191                    elem.children.push(Xml::CommentNode(cont));
192                }
193            }
194        }
195        None
196    }
197}