| 1 | //! Contains emitter configuration structure. |
| 2 | |
| 3 | use crate::writer::EventWriter; |
| 4 | use std::borrow::Cow; |
| 5 | use std::io::Write; |
| 6 | |
| 7 | /// Emitter configuration structure. |
| 8 | /// |
| 9 | /// This structure contains various options which control XML document emitter behavior. |
| 10 | #[derive (Clone, PartialEq, Eq, Debug)] |
| 11 | pub struct EmitterConfig { |
| 12 | /// Line separator used to separate lines in formatted output. Default is `"\n"`. |
| 13 | pub line_separator: Cow<'static, str>, |
| 14 | |
| 15 | /// A string which will be used for a single level of indentation. Default is `" "` |
| 16 | /// (two spaces). |
| 17 | pub indent_string: Cow<'static, str>, |
| 18 | |
| 19 | /// Whether or not the emitted document should be indented. Default is false. |
| 20 | /// |
| 21 | /// The emitter is capable to perform automatic indentation of the emitted XML document. |
| 22 | /// It is done in stream-like fashion and does not require the knowledge of the whole |
| 23 | /// document in advance. |
| 24 | /// |
| 25 | /// Sometimes, however, automatic indentation is undesirable, e.g. when you want to keep |
| 26 | /// existing layout when processing an existing XML document. Also the indentiation algorithm |
| 27 | /// is not thoroughly tested. Hence by default it is disabled. |
| 28 | pub perform_indent: bool, |
| 29 | |
| 30 | /// Whether or not characters in output events will be escaped. Default is true. |
| 31 | /// |
| 32 | /// The emitter can automatically escape characters which can't appear in PCDATA sections |
| 33 | /// or element attributes of an XML document, like `<` or `"` (in attributes). This may |
| 34 | /// introduce some overhead because then every corresponding piece of character data |
| 35 | /// should be scanned for invalid characters. |
| 36 | /// |
| 37 | /// If this option is disabled, the XML writer may produce non-well-formed documents, so |
| 38 | /// use `false` value for this option with care. |
| 39 | pub perform_escaping: bool, |
| 40 | |
| 41 | /// Whether or not to write XML document declaration at the beginning of a document. |
| 42 | /// Default is true. |
| 43 | /// |
| 44 | /// This option controls whether the document declaration should be emitted automatically |
| 45 | /// before a root element is written if it was not emitted explicitly by the user. |
| 46 | pub write_document_declaration: bool, |
| 47 | |
| 48 | /// Whether or not to convert elements with empty content to empty elements. Default is true. |
| 49 | /// |
| 50 | /// This option allows turning elements like `<a></a>` (an element with empty content) |
| 51 | /// into `<a />` (an empty element). |
| 52 | pub normalize_empty_elements: bool, |
| 53 | |
| 54 | /// Whether or not to emit CDATA events as plain characters. Default is false. |
| 55 | /// |
| 56 | /// This option forces the emitter to convert CDATA events into regular character events, |
| 57 | /// performing all the necessary escaping beforehand. This may be occasionally useful |
| 58 | /// for feeding the document into incorrect parsers which do not support CDATA. |
| 59 | pub cdata_to_characters: bool, |
| 60 | |
| 61 | /// Whether or not to keep element names to support `EndElement` events without explicit names. |
| 62 | /// Default is true. |
| 63 | /// |
| 64 | /// This option makes the emitter to keep names of written elements in order to allow |
| 65 | /// omitting names when writing closing element tags. This could incur some memory overhead. |
| 66 | pub keep_element_names_stack: bool, |
| 67 | |
| 68 | /// Whether or not to automatically insert leading and trailing spaces in emitted comments, |
| 69 | /// if necessary. Default is true. |
| 70 | /// |
| 71 | /// This is a convenience option in order for the user not to append spaces before and after |
| 72 | /// comments text in order to get more pretty comments: `<!-- something -->` instead of |
| 73 | /// `<!--something-->`. |
| 74 | pub autopad_comments: bool, |
| 75 | |
| 76 | /// Whether or not to automatically insert spaces before the trailing `/>` in self-closing |
| 77 | /// elements. Default is true. |
| 78 | /// |
| 79 | /// This option is only meaningful if `normalize_empty_elements` is true. For example, the |
| 80 | /// element `<a></a>` would be unaffected. When `normalize_empty_elements` is true, then when |
| 81 | /// this option is also true, the same element would appear `<a />`. If this option is false, |
| 82 | /// then the same element would appear `<a/>`. |
| 83 | pub pad_self_closing: bool, |
| 84 | } |
| 85 | |
| 86 | impl EmitterConfig { |
| 87 | /// Creates an emitter configuration with default values. |
| 88 | /// |
| 89 | /// You can tweak default options with builder-like pattern: |
| 90 | /// |
| 91 | /// ```rust |
| 92 | /// use xml::writer::EmitterConfig; |
| 93 | /// |
| 94 | /// let config = EmitterConfig::new() |
| 95 | /// .line_separator(" \r\n" ) |
| 96 | /// .perform_indent(true) |
| 97 | /// .normalize_empty_elements(false); |
| 98 | /// ``` |
| 99 | #[inline ] |
| 100 | #[must_use ] |
| 101 | pub fn new() -> Self { |
| 102 | Self { |
| 103 | line_separator: " \n" .into(), |
| 104 | indent_string: " " .into(), // two spaces |
| 105 | perform_indent: false, |
| 106 | perform_escaping: true, |
| 107 | write_document_declaration: true, |
| 108 | normalize_empty_elements: true, |
| 109 | cdata_to_characters: false, |
| 110 | keep_element_names_stack: true, |
| 111 | autopad_comments: true, |
| 112 | pad_self_closing: true, |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | /// Creates an XML writer with this configuration. |
| 117 | /// |
| 118 | /// This is a convenience method for configuring and creating a writer at the same time: |
| 119 | /// |
| 120 | /// ```rust |
| 121 | /// use xml::writer::EmitterConfig; |
| 122 | /// |
| 123 | /// let mut target: Vec<u8> = Vec::new(); |
| 124 | /// |
| 125 | /// let writer = EmitterConfig::new() |
| 126 | /// .line_separator(" \r\n" ) |
| 127 | /// .perform_indent(true) |
| 128 | /// .normalize_empty_elements(false) |
| 129 | /// .create_writer(&mut target); |
| 130 | /// ``` |
| 131 | /// |
| 132 | /// This method is exactly equivalent to calling `EventWriter::new_with_config()` with |
| 133 | /// this configuration object. |
| 134 | #[inline ] |
| 135 | pub fn create_writer<W: Write>(self, sink: W) -> EventWriter<W> { |
| 136 | EventWriter::new_with_config(sink, self) |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | impl Default for EmitterConfig { |
| 141 | #[inline ] |
| 142 | fn default() -> Self { |
| 143 | Self::new() |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | gen_setters!(EmitterConfig, |
| 148 | line_separator: into Cow<'static, str>, |
| 149 | indent_string: into Cow<'static, str>, |
| 150 | perform_indent: val bool, |
| 151 | write_document_declaration: val bool, |
| 152 | normalize_empty_elements: val bool, |
| 153 | cdata_to_characters: val bool, |
| 154 | keep_element_names_stack: val bool, |
| 155 | autopad_comments: val bool, |
| 156 | pad_self_closing: val bool |
| 157 | ); |
| 158 | |