xml_disassembler/builders/
extract_root_attributes.rs1use serde_json::{Map, Value};
4
5use crate::types::XmlElement;
6
7fn attr_value_to_string(v: &Value) -> String {
8 match v {
9 Value::String(s) => s.clone(),
10 Value::Number(n) => n.to_string(),
11 Value::Bool(b) => b.to_string(),
12 Value::Null => String::new(),
13 _ => serde_json::to_string(v).unwrap_or_default(),
14 }
15}
16
17pub fn extract_root_attributes(element: &XmlElement) -> XmlElement {
21 let mut attributes = Map::new();
22 if let Some(obj) = element.as_object() {
23 for (key, value) in obj {
24 let is_attr = key.starts_with('@') || key == "xmlns";
25 if is_attr {
26 let attr_key = if key == "xmlns" {
27 "@xmlns".to_string()
28 } else {
29 key.clone()
30 };
31 attributes.insert(attr_key, Value::String(attr_value_to_string(value)));
32 }
33 }
34 }
35 Value::Object(attributes)
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41 use serde_json::json;
42
43 #[test]
44 fn extracts_at_prefixed_attributes() {
45 let element = json!({
46 "@xmlns": "http://example.com",
47 "@version": "1.0",
48 "child": "ignored"
49 });
50 let attrs = extract_root_attributes(&element);
51 let obj = attrs.as_object().unwrap();
52 assert_eq!(
53 obj.get("@xmlns").and_then(|v| v.as_str()),
54 Some("http://example.com")
55 );
56 assert_eq!(obj.get("@version").and_then(|v| v.as_str()), Some("1.0"));
57 assert!(obj.get("child").is_none());
58 }
59
60 #[test]
61 fn returns_empty_for_non_object() {
62 let element = json!("string");
63 let attrs = extract_root_attributes(&element);
64 assert!(attrs.as_object().unwrap().is_empty());
65 }
66
67 #[test]
68 fn converts_xmlns_to_at_xmlns() {
69 let element = json!({ "xmlns": "http://ns.example.com", "child": {} });
70 let attrs = extract_root_attributes(&element);
71 assert_eq!(
72 attrs
73 .as_object()
74 .unwrap()
75 .get("@xmlns")
76 .and_then(|v| v.as_str()),
77 Some("http://ns.example.com")
78 );
79 }
80
81 #[test]
82 fn attr_value_number_and_bool_converted_to_string() {
83 let element = json!({ "@num": 42, "@flag": true, "child": {} });
84 let attrs = extract_root_attributes(&element);
85 let obj = attrs.as_object().unwrap();
86 assert_eq!(obj.get("@num").and_then(|v| v.as_str()), Some("42"));
87 assert_eq!(obj.get("@flag").and_then(|v| v.as_str()), Some("true"));
88 }
89
90 #[test]
91 fn attr_value_null_converted_to_empty_string() {
92 let element = json!({ "@empty": null, "child": {} });
93 let attrs = extract_root_attributes(&element);
94 assert_eq!(attrs.get("@empty").and_then(|v| v.as_str()), Some(""));
95 }
96}