diff --git a/src/xml/writer.rs b/src/xml/writer.rs index 67bb6a27..e1681289 100644 --- a/src/xml/writer.rs +++ b/src/xml/writer.rs @@ -1,11 +1,11 @@ use base64; use std::borrow::Cow; use std::io::Write; -use xml_rs::attribute::Attribute; +use xml_rs::escape::escape_str_pcdata; use xml_rs::name::Name; use xml_rs::namespace::Namespace; -use xml_rs::writer::{EmitterConfig, Error as XmlWriterError, EventWriter as XmlEventWriter}; use xml_rs::writer::events::XmlEvent as WriteXmlEvent; +use xml_rs::writer::{EmitterConfig, Error as XmlWriterError, EventWriter as XmlEventWriter}; use {Error, EventWriter as PlistEventWriter, PlistEvent, Result}; @@ -38,15 +38,16 @@ pub struct EventWriter { impl EventWriter { pub fn new(writer: W) -> EventWriter { - let config = EmitterConfig::new() + let mut config = EmitterConfig::new() .line_separator("\n") - .indent_string(" ") + .indent_string("\t") .perform_indent(true) - .write_document_declaration(true) + .write_document_declaration(false) .normalize_empty_elements(true) .cdata_to_characters(true) .keep_element_names_stack(false) .autopad_comments(true); + config.perform_escaping = false; EventWriter { xml_writer: XmlEventWriter::new_with_config(writer, config), @@ -79,13 +80,18 @@ impl EventWriter { } fn write_value(&mut self, value: &str) -> Result<()> { - self.xml_writer.write(WriteXmlEvent::Characters(value))?; + self.xml_writer + .write(WriteXmlEvent::Characters(&escape_str_pcdata(value)))?; Ok(()) } fn maybe_end_plist(&mut self) -> Result<()> { // If there are no more open tags then write the element if self.stack.len() == 1 { + // We didn't tell the xml_writer about the tag so it thinks we're already at + // the root. As such, it's not going to prettify our output, so we need to include + // the newline ourselves. + self.xml_writer.write(WriteXmlEvent::Characters("\n"))?; self.end_element("plist")?; if let Some(Element::Root) = self.stack.pop() { } else { @@ -123,14 +129,12 @@ impl PlistEventWriter for EventWriter { .push(Element::Dictionary(DictionaryState::ExpectKey)), Some(other) => self.stack.push(other), None => { - let version_name = Name::local("version"); - let version_attr = Attribute::new(version_name, "1.0"); - - self.xml_writer.write(WriteXmlEvent::StartElement { - name: Name::local("plist"), - attributes: Cow::Borrowed(&[version_attr]), - namespace: Cow::Borrowed(&self.empty_namespace), - })?; + // Write prologue + let prologue = r#" + + +"#; + self.xml_writer.write(WriteXmlEvent::Characters(prologue))?; self.stack.push(Element::Root); } @@ -227,25 +231,26 @@ mod tests { } } - let comparison = " + let comparison = " + - - Author - William Shakespeare - Lines - - It is a tale told by an idiot, - Full of sound and fury, signifying nothing. - - Death - 1564 - Height - 1.6 - Data - AAAAvgAAAAMAAAAeAAAA - Birthdate - 1981-05-16T11:32:06Z - + +\tAuthor +\tWilliam Shakespeare +\tLines +\t +\t\tIt is a tale told by an idiot, +\t\tFull of sound and fury, signifying nothing. +\t +\tDeath +\t1564 +\tHeight +\t1.6 +\tData +\tAAAAvgAAAAMAAAAeAAAA +\tBirthdate +\t1981-05-16T11:32:06Z + "; let s = String::from_utf8(cursor.into_inner()).unwrap();