xml/writer/
emitter.rs

1use std::io;
2use std::io::prelude::*;
3use std::fmt;
4use std::result;
5use std::borrow::Cow;
6use std::error::Error;
7
8use common;
9use name::{Name, OwnedName};
10use attribute::Attribute;
11use escape::{escape_str_attribute, escape_str_pcdata};
12use common::XmlVersion;
13use namespace::{NamespaceStack, NS_NO_PREFIX, NS_EMPTY_URI, NS_XMLNS_PREFIX, NS_XML_PREFIX};
14
15use writer::config::EmitterConfig;
16
17/// An error which may be returned by `XmlWriter` when writing XML events.
18#[derive(Debug)]
19pub enum EmitterError {
20    /// An I/O error occured in the underlying `Write` instance.
21    Io(io::Error),
22
23    /// Document declaration has already been written to the output stream.
24    DocumentStartAlreadyEmitted,
25
26    /// The name of the last opening element is not available.
27    LastElementNameNotAvailable,
28
29    /// The name of the last opening element is not equal to the name of the provided
30    /// closing element.
31    EndElementNameIsNotEqualToLastStartElementName,
32
33    /// End element name is not specified when it is needed, for example, when automatic
34    /// closing is not enabled in configuration.
35    EndElementNameIsNotSpecified
36}
37
38impl From<io::Error> for EmitterError {
39    fn from(err: io::Error) -> EmitterError {
40        EmitterError::Io(err)
41    }
42}
43
44impl fmt::Display for EmitterError {
45    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46        use std::error::Error;
47
48        write!(f, "emitter error: ")?;
49        match *self {
50            EmitterError::Io(ref e) =>
51                write!(f, "I/O error: {}", e),
52            ref other =>
53                write!(f, "{}", other.description()),
54        }
55    }
56}
57
58impl Error for EmitterError {
59    fn description(&self) -> &str {
60        match *self {
61            EmitterError::Io(_) =>
62                "I/O error",
63            EmitterError::DocumentStartAlreadyEmitted =>
64                "document start event has already been emitted",
65            EmitterError::LastElementNameNotAvailable =>
66                "last element name is not available",
67            EmitterError::EndElementNameIsNotEqualToLastStartElementName =>
68                "end element name is not equal to last start element name",
69            EmitterError::EndElementNameIsNotSpecified =>
70                "end element name is not specified and can't be inferred",
71        }
72    }
73}
74
75/// A result type yielded by `XmlWriter`.
76pub type Result<T> = result::Result<T, EmitterError>;
77
78// TODO: split into a low-level fast writer without any checks and formatting logic and a
79// high-level indenting validating writer
80pub struct Emitter {
81    config: EmitterConfig,
82
83    nst: NamespaceStack,
84
85    indent_level: usize,
86    indent_stack: Vec<IndentFlags>,
87
88    element_names: Vec<OwnedName>,
89
90    start_document_emitted: bool,
91    just_wrote_start_element: bool
92}
93
94impl Emitter {
95    pub fn new(config: EmitterConfig) -> Emitter {
96        Emitter {
97            config,
98
99            nst: NamespaceStack::empty(),
100
101            indent_level: 0,
102            indent_stack: vec![IndentFlags::WroteNothing],
103
104            element_names: Vec::new(),
105
106            start_document_emitted: false,
107            just_wrote_start_element: false
108        }
109    }
110}
111
112#[derive(Copy, Clone, Eq, PartialEq, Debug)]
113enum IndentFlags {
114    WroteNothing,
115    WroteMarkup,
116    WroteText,
117}
118
119impl Emitter {
120    /// Returns the current state of namespaces.
121    #[inline]
122    pub fn namespace_stack_mut(&mut self) -> &mut NamespaceStack {
123        &mut self.nst
124    }
125
126    #[inline]
127    fn wrote_text(&self) -> bool {
128        *self.indent_stack.last().unwrap() == IndentFlags::WroteText
129    }
130
131    #[inline]
132    fn wrote_markup(&self) -> bool {
133        *self.indent_stack.last().unwrap() == IndentFlags::WroteMarkup
134    }
135
136    #[inline]
137    fn set_wrote_text(&mut self) {
138        *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteText;
139    }
140
141    #[inline]
142    fn set_wrote_markup(&mut self) {
143        *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteMarkup;
144    }
145
146    #[inline]
147    fn reset_state(&mut self) {
148        *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteNothing;
149    }
150
151    fn write_newline<W: Write>(&mut self, target: &mut W, level: usize) -> Result<()> {
152        target.write(self.config.line_separator.as_bytes())?;
153        for _ in 0..level {
154            target.write(self.config.indent_string.as_bytes())?;
155        }
156        Ok(())
157    }
158
159    fn before_markup<W: Write>(&mut self, target: &mut W) -> Result<()> {
160        if self.config.perform_indent && !self.wrote_text() &&
161           (self.indent_level > 0 || self.wrote_markup()) {
162            let indent_level = self.indent_level;
163            self.write_newline(target, indent_level)?;
164            if self.indent_level > 0 && self.config.indent_string.len() > 0 {
165                self.after_markup();
166            }
167        }
168        Ok(())
169    }
170
171    fn after_markup(&mut self) {
172        self.set_wrote_markup();
173    }
174
175    fn before_start_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
176        self.before_markup(target)?;
177        self.indent_stack.push(IndentFlags::WroteNothing);
178        Ok(())
179    }
180
181    fn after_start_element(&mut self) {
182        self.after_markup();
183        self.indent_level += 1;
184    }
185
186    fn before_end_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
187        if self.config.perform_indent && self.indent_level > 0 && self.wrote_markup() &&
188           !self.wrote_text() {
189            let indent_level = self.indent_level;
190            self.write_newline(target, indent_level - 1)
191        } else {
192            Ok(())
193        }
194    }
195
196    fn after_end_element(&mut self) {
197        if self.indent_level > 0 {
198            self.indent_level -= 1;
199            self.indent_stack.pop();
200        }
201        self.set_wrote_markup();
202    }
203
204    fn after_text(&mut self) {
205        self.set_wrote_text();
206    }
207
208    pub fn emit_start_document<W: Write>(&mut self, target: &mut W,
209                                         version: XmlVersion,
210                                         encoding: &str,
211                                         standalone: Option<bool>) -> Result<()> {
212        if self.start_document_emitted {
213            return Err(EmitterError::DocumentStartAlreadyEmitted);
214        }
215        self.start_document_emitted = true;
216
217        self.before_markup(target)?;
218        let result = {
219            let mut write = move || {
220                write!(target, "<?xml version=\"{}\" encoding=\"{}\"", version, encoding)?;
221
222                if let Some(standalone) = standalone {
223                    write!(target, " standalone=\"{}\"", if standalone { "yes" } else { "no" })?;
224                }
225
226                write!(target, "?>")?;
227
228                Ok(())
229            };
230            write()
231        };
232        self.after_markup();
233
234        result
235    }
236
237    fn check_document_started<W: Write>(&mut self, target: &mut W) -> Result<()> {
238        if !self.start_document_emitted && self.config.write_document_declaration {
239            self.emit_start_document(target, common::XmlVersion::Version10, "utf-8", None)
240        } else {
241            Ok(())
242        }
243    }
244
245    fn fix_non_empty_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
246        if self.config.normalize_empty_elements && self.just_wrote_start_element {
247            self.just_wrote_start_element = false;
248            target.write(b">").map(|_| ()).map_err(From::from)
249        } else {
250            Ok(())
251        }
252    }
253
254    pub fn emit_processing_instruction<W: Write>(&mut self,
255                                                 target: &mut W,
256                                                 name: &str,
257                                                 data: Option<&str>) -> Result<()> {
258        self.check_document_started(target)?;
259        self.fix_non_empty_element(target)?;
260
261        self.before_markup(target)?;
262
263        let result = {
264            let mut write = || {
265                write!(target, "<?{}", name)?;
266
267                if let Some(data) = data {
268                    write!(target, " {}", data)?;
269                }
270
271                write!(target, "?>")?;
272
273                Ok(())
274            };
275            write()
276        };
277
278        self.after_markup();
279
280        result
281    }
282
283    fn emit_start_element_initial<W>(&mut self, target: &mut W,
284                                     name: Name,
285                                     attributes: &[Attribute]) -> Result<()>
286        where W: Write
287    {
288        self.check_document_started(target)?;
289        self.fix_non_empty_element(target)?;
290        self.before_start_element(target)?;
291        write!(target, "<{}", name.repr_display())?;
292        self.emit_current_namespace_attributes(target)?;
293        self.emit_attributes(target, attributes)?;
294        self.after_start_element();
295        Ok(())
296    }
297
298    pub fn emit_start_element<W>(&mut self, target: &mut W,
299                                 name: Name,
300                                 attributes: &[Attribute]) -> Result<()>
301        where W: Write
302    {
303        if self.config.keep_element_names_stack {
304            self.element_names.push(name.to_owned());
305        }
306
307        self.emit_start_element_initial(target, name, attributes)?;
308        self.just_wrote_start_element = true;
309
310        if !self.config.normalize_empty_elements {
311            write!(target, ">")?;
312        }
313
314        Ok(())
315    }
316
317    pub fn emit_current_namespace_attributes<W>(&mut self, target: &mut W) -> Result<()>
318        where W: Write
319    {
320        for (prefix, uri) in self.nst.peek() {
321            match prefix {
322                // internal namespaces are not emitted
323                NS_XMLNS_PREFIX | NS_XML_PREFIX => Ok(()),
324                //// there is already a namespace binding with this prefix in scope
325                //prefix if self.nst.get(prefix) == Some(uri) => Ok(()),
326                // emit xmlns only if it is overridden
327                NS_NO_PREFIX => if uri != NS_EMPTY_URI {
328                    write!(target, " xmlns=\"{}\"", uri)
329                } else { Ok(()) },
330                // everything else
331                prefix => write!(target, " xmlns:{}=\"{}\"", prefix, uri)
332            }?;
333        }
334        Ok(())
335    }
336
337    pub fn emit_attributes<W: Write>(&mut self, target: &mut W,
338                                      attributes: &[Attribute]) -> Result<()> {
339        for attr in attributes.iter() {
340            write!(
341                target, " {}=\"{}\"",
342                attr.name.repr_display(),
343                if self.config.perform_escaping { escape_str_attribute(attr.value) } else { Cow::Borrowed(attr.value) }
344            )?
345        }
346        Ok(())
347    }
348
349    pub fn emit_end_element<W: Write>(&mut self, target: &mut W,
350                                      name: Option<Name>) -> Result<()> {
351        let owned_name = if self.config.keep_element_names_stack {
352            Some(self.element_names.pop().ok_or(EmitterError::LastElementNameNotAvailable)?)
353        } else {
354            None
355        };
356
357        // Check that last started element name equals to the provided name, if there are both
358        if let Some(ref last_name) = owned_name {
359            if let Some(ref name) = name {
360                if last_name.borrow() != *name {
361                    return Err(EmitterError::EndElementNameIsNotEqualToLastStartElementName);
362                }
363            }
364        }
365
366        if let Some(name) = owned_name.as_ref().map(|n| n.borrow()).or(name) {
367            if self.config.normalize_empty_elements && self.just_wrote_start_element {
368                self.just_wrote_start_element = false;
369                // TODO: make this space configurable
370                let result = target.write(b" />").map_err(From::from);
371                self.after_end_element();
372                result.map(|_| ())
373            } else {
374                self.just_wrote_start_element = false;
375
376                self.before_end_element(target)?;
377                let result = write!(target, "</{}>", name.repr_display()).map_err(From::from);
378                self.after_end_element();
379
380                result
381            }
382        } else {
383            Err(EmitterError::EndElementNameIsNotSpecified)
384        }
385    }
386
387    pub fn emit_cdata<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
388        self.fix_non_empty_element(target)?;
389        if self.config.cdata_to_characters {
390            self.emit_characters(target, content)
391        } else {
392            // TODO: escape ']]>' characters in CDATA as two adjacent CDATA blocks
393            target.write(b"<![CDATA[")?;
394            target.write(content.as_bytes())?;
395            target.write(b"]]>")?;
396
397            self.after_text();
398
399            Ok(())
400        }
401    }
402
403    pub fn emit_characters<W: Write>(&mut self, target: &mut W,
404                                      content: &str) -> Result<()> {
405        self.fix_non_empty_element(target)?;
406        target.write(
407            (if self.config.perform_escaping {
408                escape_str_pcdata(content)
409            } else {
410                Cow::Borrowed(content)
411            }).as_bytes()
412        )?;
413        self.after_text();
414        Ok(())
415    }
416
417    pub fn emit_comment<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
418        self.fix_non_empty_element(target)?;
419
420        // TODO: add escaping dashes at the end of the comment
421
422        let autopad_comments = self.config.autopad_comments;
423        let write = |target: &mut W| -> Result<()> {
424            target.write(b"<!--")?;
425
426            if autopad_comments && !content.starts_with(char::is_whitespace) {
427                target.write(b" ")?;
428            }
429
430            target.write(content.as_bytes())?;
431
432            if autopad_comments && !content.ends_with(char::is_whitespace) {
433                target.write(b" ")?;
434            }
435
436            target.write(b"-->")?;
437
438            Ok(())
439        };
440
441        self.before_markup(target)?;
442        let result = write(target);
443        self.after_markup();
444
445        result
446    }
447}