1 | //! Contains emitter configuration structure. |
2 | |
3 | use std::borrow::Cow; |
4 | use std::io::Write; |
5 | use crate::writer::EventWriter; |
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() -> EmitterConfig { |
102 | EmitterConfig { |
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() -> EmitterConfig { |
143 | EmitterConfig::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 | |