1 use std::io; 2 use std::io::prelude::*; 3 use std::fmt; 4 use std::result; 5 use std::borrow::Cow; 6 use std::error::Error; 7 8 use common; 9 use name::{Name, OwnedName}; 10 use attribute::Attribute; 11 use escape::{escape_str_attribute, escape_str_pcdata}; 12 use common::XmlVersion; 13 use namespace::{NamespaceStack, NS_NO_PREFIX, NS_EMPTY_URI, NS_XMLNS_PREFIX, NS_XML_PREFIX}; 14 15 use writer::config::EmitterConfig; 16 17 /// An error which may be returned by `XmlWriter` when writing XML events. 18 #[derive(Debug)] 19 pub 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 38 impl From<io::Error> for EmitterError { from(err: io::Error) -> EmitterError39 fn from(err: io::Error) -> EmitterError { 40 EmitterError::Io(err) 41 } 42 } 43 44 impl fmt::Display for EmitterError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result45 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 58 impl Error for EmitterError { description(&self) -> &str59 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`. 76 pub 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 80 pub 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 94 impl Emitter { new(config: EmitterConfig) -> Emitter95 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)] 113 enum IndentFlags { 114 WroteNothing, 115 WroteMarkup, 116 WroteText, 117 } 118 119 impl Emitter { 120 /// Returns the current state of namespaces. 121 #[inline] namespace_stack_mut(&mut self) -> &mut NamespaceStack122 pub fn namespace_stack_mut(&mut self) -> &mut NamespaceStack { 123 &mut self.nst 124 } 125 126 #[inline] wrote_text(&self) -> bool127 fn wrote_text(&self) -> bool { 128 *self.indent_stack.last().unwrap() == IndentFlags::WroteText 129 } 130 131 #[inline] wrote_markup(&self) -> bool132 fn wrote_markup(&self) -> bool { 133 *self.indent_stack.last().unwrap() == IndentFlags::WroteMarkup 134 } 135 136 #[inline] set_wrote_text(&mut self)137 fn set_wrote_text(&mut self) { 138 *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteText; 139 } 140 141 #[inline] set_wrote_markup(&mut self)142 fn set_wrote_markup(&mut self) { 143 *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteMarkup; 144 } 145 146 #[inline] reset_state(&mut self)147 fn reset_state(&mut self) { 148 *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteNothing; 149 } 150 write_newline<W: Write>(&mut self, target: &mut W, level: usize) -> Result<()>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 before_markup<W: Write>(&mut self, target: &mut W) -> Result<()>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 after_markup(&mut self)171 fn after_markup(&mut self) { 172 self.set_wrote_markup(); 173 } 174 before_start_element<W: Write>(&mut self, target: &mut W) -> Result<()>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 after_start_element(&mut self)181 fn after_start_element(&mut self) { 182 self.after_markup(); 183 self.indent_level += 1; 184 } 185 before_end_element<W: Write>(&mut self, target: &mut W) -> Result<()>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 after_end_element(&mut self)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 after_text(&mut self)204 fn after_text(&mut self) { 205 self.set_wrote_text(); 206 } 207 emit_start_document<W: Write>(&mut self, target: &mut W, version: XmlVersion, encoding: &str, standalone: Option<bool>) -> Result<()>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 check_document_started<W: Write>(&mut self, target: &mut W) -> Result<()>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 fix_non_empty_element<W: Write>(&mut self, target: &mut W) -> Result<()>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 emit_processing_instruction<W: Write>(&mut self, target: &mut W, name: &str, data: Option<&str>) -> Result<()>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 emit_start_element_initial<W>(&mut self, target: &mut W, name: Name, attributes: &[Attribute]) -> Result<()> where W: Write283 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 emit_start_element<W>(&mut self, target: &mut W, name: Name, attributes: &[Attribute]) -> Result<()> where W: Write298 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 emit_current_namespace_attributes<W>(&mut self, target: &mut W) -> Result<()> where W: Write317 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 emit_attributes<W: Write>(&mut self, target: &mut W, attributes: &[Attribute]) -> Result<()>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 emit_end_element<W: Write>(&mut self, target: &mut W, name: Option<Name>) -> Result<()>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 emit_cdata<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()>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 emit_characters<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()>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 emit_comment<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()>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 } 448