Skip to main content

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}