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}