xml_disassembler/parsers/
parse_to_xml_object.rs1use crate::parsers::{extract_xml_declaration_from_raw, parse_xml_from_str};
4use crate::types::XmlElement;
5use tokio::fs;
6
7pub async fn parse_to_xml_object(file_path: &str) -> Option<XmlElement> {
8 if file_path.to_lowercase().ends_with(".xml") {
9 let content = fs::read_to_string(file_path).await.ok()?;
10 let mut parsed = parse_xml_from_str(&content, file_path)?;
11 if let (Some(obj), Some(decl)) = (
14 parsed.as_object_mut(),
15 extract_xml_declaration_from_raw(&content),
16 ) {
17 obj.insert("?xml".to_string(), decl);
18 }
19 return Some(parsed);
20 }
21
22 let content = fs::read_to_string(file_path).await.ok()?;
23
24 if file_path.to_lowercase().ends_with(".yaml") || file_path.to_lowercase().ends_with(".yml") {
25 return serde_yaml::from_str(&content).ok();
26 }
27
28 if file_path.to_lowercase().ends_with(".json5") {
29 return json5::from_str(&content).ok();
30 }
31
32 if file_path.to_lowercase().ends_with(".json") {
33 return serde_json::from_str(&content).ok();
34 }
35
36 None
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42
43 #[tokio::test]
44 async fn parse_to_xml_object_json() {
45 let dir = tempfile::tempdir().unwrap();
46 let path = dir.path().join("test.json");
47 std::fs::write(&path, r#"{"root":{"a":1}}"#).unwrap();
48 let out = parse_to_xml_object(path.to_str().unwrap()).await;
49 assert!(out.is_some());
50 let obj = out.unwrap();
51 assert!(obj.get("root").is_some());
52 }
53
54 #[tokio::test]
55 async fn parse_to_xml_object_yaml() {
56 let dir = tempfile::tempdir().unwrap();
57 let path = dir.path().join("test.yaml");
58 std::fs::write(&path, "root:\n a: 1\n").unwrap();
59 let out = parse_to_xml_object(path.to_str().unwrap()).await;
60 assert!(out.is_some());
61 }
62
63 #[tokio::test]
64 async fn parse_to_xml_object_yml_extension() {
65 let dir = tempfile::tempdir().unwrap();
66 let path = dir.path().join("test.yml");
67 std::fs::write(&path, "root: {}").unwrap();
68 let out = parse_to_xml_object(path.to_str().unwrap()).await;
69 assert!(out.is_some());
70 }
71
72 #[tokio::test]
73 async fn parse_to_xml_object_json5() {
74 let dir = tempfile::tempdir().unwrap();
75 let path = dir.path().join("test.json5");
76 std::fs::write(&path, "{ root: { a: 1 } }").unwrap();
77 let out = parse_to_xml_object(path.to_str().unwrap()).await;
78 assert!(out.is_some());
79 }
80
81 #[tokio::test]
82 async fn parse_to_xml_object_unsupported_returns_none() {
83 let dir = tempfile::tempdir().unwrap();
84 let path = dir.path().join("test.txt");
85 std::fs::write(&path, "not xml").unwrap();
86 let out = parse_to_xml_object(path.to_str().unwrap()).await;
87 assert!(out.is_none());
88 }
89
90 #[tokio::test]
91 async fn parse_to_xml_object_xml_with_declaration_and_xmlns() {
92 let dir = tempfile::tempdir().unwrap();
93 let path = dir.path().join("meta.xml");
94 let xml = r#"<?xml version="1.0" encoding="UTF-8"?><root xmlns="http://example.com"><a>1</a></root>"#;
95 std::fs::write(&path, xml).unwrap();
96 let out = parse_to_xml_object(path.to_str().unwrap()).await;
97 assert!(out.is_some());
98 let obj = out.unwrap();
99 assert!(obj.get("?xml").is_some());
100 let root = obj.get("root").and_then(|r| r.as_object()).unwrap();
101 assert_eq!(
102 root.get("@xmlns").and_then(|v| v.as_str()),
103 Some("http://example.com")
104 );
105 }
106}