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 | |
6 | pub use self::config::EmitterConfig; |
7 | pub use self::emitter::EmitterError as Error; |
8 | pub use self::emitter::Result; |
9 | pub use self::events::XmlEvent; |
10 | |
11 | use self::emitter::Emitter; |
12 | |
13 | use std::io::prelude::*; |
14 | |
15 | mod config; |
16 | mod emitter; |
17 | pub mod events; |
18 | |
19 | /// A wrapper around an `std::io::Write` instance which emits XML document according to provided |
20 | /// events. |
21 | pub struct EventWriter<W> { |
22 | sink: W, |
23 | emitter: Emitter, |
24 | } |
25 | |
26 | impl<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) => self.emitter.emit_comment(&mut self.sink, content), |
67 | XmlEvent::CData(content) => self.emitter.emit_cdata(&mut self.sink, content), |
68 | XmlEvent::Characters(content) => self.emitter.emit_characters(&mut self.sink, content), |
69 | } |
70 | } |
71 | |
72 | /// Returns a mutable reference to the underlying `Writer`. |
73 | /// |
74 | /// Note that having a reference to the underlying sink makes it very easy to emit invalid XML |
75 | /// documents. Use this method with care. Valid use cases for this method include accessing |
76 | /// methods like `Write::flush`, which do not emit new data but rather change the state |
77 | /// of the stream itself. |
78 | pub fn inner_mut(&mut self) -> &mut W { |
79 | &mut self.sink |
80 | } |
81 | |
82 | /// Unwraps this `EventWriter`, returning the underlying writer. |
83 | /// |
84 | /// Note that this is a destructive operation: unwrapping a writer and then wrapping |
85 | /// it again with `EventWriter::new()` will create a fresh writer whose state will be |
86 | /// blank; for example, accumulated namespaces will be reset. |
87 | pub fn into_inner(self) -> W { |
88 | self.sink |
89 | } |
90 | } |
91 | |