xml_builder/xml.rs
1use std::io::Write;
2
3use crate::{Result, XMLElement, XMLVersion};
4
5/// Structure representing a XML document.
6/// It must be used to create a XML document.
7pub struct XML {
8 /// The XML version to set for the document.
9 ///
10 /// Defaults to `XML1.0`.
11 version: XMLVersion,
12
13 /// XML encoding attribute.
14 ///
15 /// The optional encoding to set for the document.
16 ///
17 /// Defaults to `None`.
18 encoding: Option<String>,
19
20 /// XML standalone attribute.
21 ///
22 /// A `None` value indicates no displaying.
23 ///
24 /// Defaults to `None`
25 standalone: Option<bool>,
26
27 /// Whether the XML attributes should be sorted or not.
28 ///
29 /// Defaults to `false`.
30 sort_attributes: bool,
31
32 /// Whether we want to indentate the document.
33 ///
34 /// Defaults to `true`.
35 indent: bool,
36
37 /// Whether we want to break lines or not.
38 ///
39 /// Defaults to `true`.
40 break_lines: bool,
41
42 /// Whether we want to expand empty tags or not.
43 ///
44 /// Defaults to `false`.
45 expand_empty_tags: bool,
46
47 /// The root XML element.
48 root: Option<XMLElement>,
49}
50
51impl XML {
52 pub(crate) const fn new(
53 version: XMLVersion,
54 encoding: Option<String>,
55 standalone: Option<bool>,
56 indent: bool,
57 sort_attributes: bool,
58 break_lines: bool,
59 expand_empty_tags: bool,
60 ) -> Self {
61 Self {
62 version,
63 encoding,
64 standalone,
65 indent,
66 sort_attributes,
67 break_lines,
68 expand_empty_tags,
69 root: None,
70 }
71 }
72
73 /// Sets the XML document root element.
74 ///
75 /// # Arguments
76 ///
77 /// `element` - An `XMLElement` qualified as root for the XML document.
78 pub fn set_root_element(&mut self, element: XMLElement) {
79 self.root = Some(element);
80 }
81
82 /// Generates an XML document into the specified `Writer`.
83 ///
84 /// Consumes the XML object.
85 pub fn generate<W: Write>(self, mut writer: W) -> Result<()> {
86 write!(
87 writer,
88 r#"<?xml version="{}"{encoding}{standalone}?>"#,
89 self.version,
90 encoding = self
91 .encoding
92 .map_or_else(String::default, |encoding| format!(
93 " encoding=\"{encoding}\""
94 )),
95 standalone = if let Some(standalone) = self.standalone
96 && standalone
97 {
98 " standalone=\"yes\"".to_string()
99 } else {
100 String::default()
101 }
102 )?;
103
104 if self.break_lines {
105 writeln!(writer)?;
106 }
107
108 // And then XML elements if present...
109 if let Some(elem) = &self.root {
110 elem.render(
111 &mut writer,
112 self.sort_attributes,
113 self.indent,
114 self.break_lines,
115 self.expand_empty_tags,
116 )?;
117 }
118
119 Ok(())
120 }
121}