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] new(sink: W) -> EventWriter<W>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] new_with_config(sink: W, config: EmitterConfig) -> EventWriter<W>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. write<'a, E>(&mut self, event: E) -> Result<()> where E: Into<XmlEvent<'a>>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. inner_mut(&mut self) -> &mut W78 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. into_inner(self) -> W87 pub fn into_inner(self) -> W { 88 self.sink 89 } 90 } 91