1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use std::io::Write;

use crate::{Result, XMLElement, XMLVersion};

/// Structure representing a XML document.
/// It must be used to create a XML document.
pub struct XML {
    /// The XML version to set for the document.
    ///
    /// Defaults to `XML1.0`.
    version: XMLVersion,

    /// The encoding to set for the document.
    ///
    /// Defaults to `UTF-8`.
    encoding: String,

    /// XML standalone attribute.
    ///
    /// A `None` value indicates no displaying.
    ///
    /// Defaults to `None`
    standalone: Option<bool>,

    /// Whether the XML attributes should be sorted or not.
    ///
    /// Defaults to `false`.
    sort_attributes: bool,

    /// Whether we want to indentate the document.
    ///
    /// Defaults to `true`.
    indent: bool,

    /// The root XML element.
    root: Option<XMLElement>,
}

impl XML {
    pub(crate) fn new(
        version: XMLVersion,
        encoding: String,
        standalone: Option<bool>,
        indent: bool,
        sort_attributes: bool,
    ) -> Self {
        Self {
            version,
            encoding,
            standalone,
            indent,
            sort_attributes,
            root: None,
        }
    }

    /// Sets the XML document root element.
    ///
    /// # Arguments
    ///
    /// `element` - An XMLElement qualified as root for the XML document.
    pub fn set_root_element(&mut self, element: XMLElement) {
        self.root = Some(element);
    }

    /// Generates an XML document into the specified `Writer`.
    ///
    /// Consumes the XML object.
    pub fn generate<W: Write>(self, mut writer: W) -> Result<()> {
        let standalone_attribute = match self.standalone {
            Some(_) => r#" standalone="yes""#.to_string(),
            None => String::default(),
        };

        writeln!(
            writer,
            r#"<?xml version="{}" encoding="{}"{}?>"#,
            self.version.to_string(),
            self.encoding,
            standalone_attribute
        )?;

        // And then XML elements if present...
        if let Some(elem) = &self.root {
            elem.render(&mut writer, self.sort_attributes, self.indent)?;
        }

        Ok(())
    }
}