xml.rs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. use std::fmt::{Display};
  2. use std::io::{self, Write};
  3. use std::iter::repeat;
  4. /// An `XMLWriter` is a wrapper over a `Write` value that provides
  5. /// helper functions for generating (mostly) well-formed XML.
  6. pub struct XMLWriter<'a>{
  7. writer: &'a mut Write,
  8. indent: usize,
  9. }
  10. impl<'a> XMLWriter<'a> {
  11. /// Create a new XMLWriter and add an XML version/encoding header
  12. /// on top
  13. pub fn start(buf: &'a mut Write) -> io::Result<XMLWriter<'a>> {
  14. writeln!(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>")?;
  15. Ok(XMLWriter { writer: buf, indent: 0, })
  16. }
  17. fn indent(&mut self) -> io::Result<()> {
  18. write!(self.writer, "{}", repeat(' ').take(self.indent).collect::<String>())?;
  19. Ok(())
  20. }
  21. /// create an complete tag with the given attributes
  22. pub fn tag(&mut self, name: &str, attrs: &[(&str, &Display)]) -> io::Result<()> {
  23. self.indent()?;
  24. write!(self.writer, "<{}", name)?;
  25. for &(k, v) in attrs {
  26. write!(self.writer, " {}=\"{}\"", k, v)?;
  27. }
  28. writeln!(self.writer, "/>")?;
  29. Ok(())
  30. }
  31. /// create an open tag with the given attributes; you must close
  32. /// it manually later
  33. pub fn open(&mut self, name: &str, attrs: &[(&str, &Display)]) -> io::Result<()> {
  34. self.indent()?;
  35. write!(self.writer, "<{}", name)?;
  36. for &(k, v) in attrs {
  37. write!(self.writer, " {}=\"{}\"", k, v)?;
  38. }
  39. writeln!(self.writer, ">")?;
  40. Ok(())
  41. }
  42. /// close a tag with the given attributes
  43. pub fn close(&mut self, name: &str) -> io::Result<()> {
  44. self.indent()?;
  45. write!(self.writer, "</{}>", name)?;
  46. Ok(())
  47. }
  48. /// create an open-close tag pair with the given attributes,
  49. /// calling the provided function in order to fill in the interior
  50. /// tags as well
  51. pub fn block<F>(
  52. &mut self,
  53. name: &str,
  54. attrs: &[(&str, &Display)],
  55. cb: F
  56. ) -> io::Result<()>
  57. where F: FnOnce(&mut XMLWriter<'a>) -> io::Result<()>
  58. {
  59. self.indent()?;
  60. write!(self.writer, "<{}", name)?;
  61. for &(k, v) in attrs {
  62. write!(self.writer, " {}=\"{}\"", k, v)?;
  63. }
  64. writeln!(self.writer, ">")?;
  65. self.indent += 2;
  66. cb(self)?;
  67. self.indent -= 2;
  68. write!(self.writer, "</{}>", name)?;
  69. Ok(())
  70. }
  71. }