xml/writer/
mod.rs

1//! Contains high-level interface for an events-based XML emitter.
2//!
3//! The most important type in this module is `EventWriter` which allows writing an XML document
4//! to some output stream.
5
6pub use self::emitter::Result;
7pub use self::emitter::EmitterError as Error;
8pub use self::config::EmitterConfig;
9pub use self::events::XmlEvent;
10
11use self::emitter::Emitter;
12
13use std::io::prelude::*;
14
15mod emitter;
16mod config;
17pub mod events;
18
19/// A wrapper around an `std::io::Write` instance which emits XML document according to provided
20/// events.
21pub struct EventWriter<W> {
22    sink: W,
23    emitter: Emitter
24}
25
26impl<W: Write> EventWriter<W> {
27    /// Creates a new `EventWriter` out of an `std::io::Write` instance using the default
28    /// configuration.
29    #[inline]
30    pub fn new(sink: W) -> EventWriter<W> {
31        EventWriter::new_with_config(sink, EmitterConfig::new())
32    }
33
34    /// Creates a new `EventWriter` out of an `std::io::Write` instance using the provided
35    /// configuration.
36    #[inline]
37    pub fn new_with_config(sink: W, config: EmitterConfig) -> EventWriter<W> {
38        EventWriter {
39            sink,
40            emitter: Emitter::new(config)
41        }
42    }
43
44    /// Writes the next piece of XML document according to the provided event.
45    ///
46    /// Note that output data may not exactly correspond to the written event because
47    /// of various configuration options. For example, `XmlEvent::EndElement` may
48    /// correspond to a separate closing element or it may cause writing an empty element.
49    /// Another example is that `XmlEvent::CData` may be represented as characters in
50    /// the output stream.
51    pub fn write<'a, E>(&mut self, event: E) -> Result<()> where E: Into<XmlEvent<'a>> {
52        match event.into() {
53            XmlEvent::StartDocument { version, encoding, standalone } =>
54                self.emitter.emit_start_document(&mut self.sink, version, encoding.unwrap_or("UTF-8"), standalone),
55            XmlEvent::ProcessingInstruction { name, data } =>
56                self.emitter.emit_processing_instruction(&mut self.sink, name, data),
57            XmlEvent::StartElement { name, attributes, namespace } => {
58                self.emitter.namespace_stack_mut().push_empty().checked_target().extend(namespace.as_ref());
59                self.emitter.emit_start_element(&mut self.sink, name, &attributes)
60            }
61            XmlEvent::EndElement { name } => {
62                let r = self.emitter.emit_end_element(&mut self.sink, name);
63                self.emitter.namespace_stack_mut().try_pop();
64                r
65            }
66            XmlEvent::Comment(content) =>
67                self.emitter.emit_comment(&mut self.sink, content),
68            XmlEvent::CData(content) =>
69                self.emitter.emit_cdata(&mut self.sink, content),
70            XmlEvent::Characters(content) =>
71                self.emitter.emit_characters(&mut self.sink, content)
72        }
73    }
74
75    /// Returns a mutable reference to the underlying `Writer`.
76    ///
77    /// Note that having a reference to the underlying sink makes it very easy to emit invalid XML
78    /// documents. Use this method with care. Valid use cases for this method include accessing
79    /// methods like `Write::flush`, which do not emit new data but rather change the state
80    /// of the stream itself.
81    pub fn inner_mut(&mut self) -> &mut W {
82        &mut self.sink
83    }
84
85    /// Unwraps this `EventWriter`, returning the underlying writer.
86    ///
87    /// Note that this is a destructive operation: unwrapping a writer and then wrapping
88    /// it again with `EventWriter::new()` will create a fresh writer whose state will be
89    /// blank; for example, accumulated namespaces will be reset.
90    pub fn into_inner(self) -> W {
91        self.sink
92    }
93}