Skip to main content

xml_disassembler/transformers/
formats.rs

1//! Transform XmlElement to various formats.
2
3use serde_json::Value;
4
5use crate::types::XmlElement;
6
7pub async fn transform_to_yaml(parsed_xml: &XmlElement) -> String {
8    serde_yaml::to_string(parsed_xml).unwrap_or_default()
9}
10
11pub async fn transform_to_json5(parsed_xml: &XmlElement) -> String {
12    serde_json::to_string_pretty(parsed_xml).unwrap_or_default()
13}
14
15pub async fn transform_to_json(parsed_xml: &XmlElement) -> String {
16    serde_json::to_string_pretty(parsed_xml).unwrap_or_default()
17}
18
19pub async fn transform_to_toml(parsed_xml: &XmlElement) -> String {
20    toml::to_string_pretty(&convert_json_to_toml_value(parsed_xml)).unwrap_or_default()
21}
22
23pub async fn transform_to_ini(parsed_xml: &XmlElement) -> String {
24    // Simple INI-like output - Node's ini package produces nested structure
25    // We output a basic section/key=value format
26    convert_to_ini_string(parsed_xml)
27}
28
29fn convert_json_to_toml_value(v: &Value) -> toml::Value {
30    match v {
31        Value::Null => toml::Value::String(String::new()),
32        Value::Bool(b) => toml::Value::Boolean(*b),
33        Value::Number(n) => {
34            if let Some(i) = n.as_i64() {
35                toml::Value::Integer(i)
36            } else if let Some(f) = n.as_f64() {
37                toml::Value::Float(f)
38            } else {
39                toml::Value::String(n.to_string())
40            }
41        }
42        Value::String(s) => toml::Value::String(s.clone()),
43        Value::Array(arr) => {
44            toml::Value::Array(arr.iter().map(convert_json_to_toml_value).collect())
45        }
46        Value::Object(obj) => {
47            let mut table = toml::map::Map::new();
48            for (k, v) in obj {
49                table.insert(k.clone(), convert_json_to_toml_value(v));
50            }
51            toml::Value::Table(table)
52        }
53    }
54}
55
56fn convert_to_ini_string(v: &Value) -> String {
57    let mut out = String::new();
58    if let Some(obj) = v.as_object() {
59        for (section, value) in obj {
60            if section.starts_with('@')
61                || section == "?xml"
62                || section == "#text"
63                || section == "#cdata"
64            {
65                continue;
66            }
67            out.push_str(&format!("[{}]\n", section));
68            if let Some(inner) = value.as_object() {
69                for (k, val) in inner {
70                    if !k.starts_with('@')
71                        && k != "#text"
72                        && k != "#cdata"
73                        && k != "#comment"
74                        && k != "#text-tail"
75                    {
76                        if let Some(s) = val.as_str() {
77                            out.push_str(&format!("{} = {}\n", k, s));
78                        }
79                    }
80                }
81            }
82            out.push('\n');
83        }
84    }
85    out
86}