use super::*;
use serde_json::{json, to_string_pretty};
use std::fs::File;
use std::io::prelude::*;
#[test]
fn test_numbers() {
let expected = json!({
"a": {
"b":[ 12345, 12345.0, 12345.6 ]
}
});
let result = xml_string_to_json(
String::from("<a><b>12345</b><b>12345.0</b><b>12345.6</b></a>"),
&Config::new_with_defaults(),
);
assert_eq!(expected, result.unwrap());
}
#[test]
fn test_empty_elements_valid() {
let mut conf = Config::new_with_custom_values(true, "", "text", NullValue::EmptyObject);
let xml = r#"<a b="1"><x/></a>"#;
let expected = json!({ "a": {"b":1, "x":{}} });
let result = xml_string_to_json(xml.to_owned(), &conf);
assert_eq!(expected, result.unwrap());
conf.empty_element_handling = NullValue::Null;
let expected = json!({ "a": {"b":1, "x":null} });
let result = xml_string_to_json(xml.to_owned(), &conf);
assert_eq!(expected, result.unwrap());
conf.empty_element_handling = NullValue::Ignore;
let expected = json!({ "a": {"b":1} });
let result = xml_string_to_json(xml.to_owned(), &conf);
assert_eq!(expected, result.unwrap());
conf.empty_element_handling = NullValue::EmptyString;
let expected = json!({ "a": {"b":1, "x": ""} });
let result = xml_string_to_json(xml.to_owned(), &conf);
assert_eq!(expected, result.unwrap());
}
#[test]
fn test_empty_elements_invalid() {
let conf = Config::new_with_custom_values(true, "", "text", NullValue::Ignore);
let expected = json!({ "a": null });
let xml = r#"<a><x/></a>"#;
let result = xml_string_to_json(xml.to_owned(), &conf);
assert_eq!(expected, result.unwrap());
let xml = r#"<a />"#;
let result = xml_string_to_json(xml.to_owned(), &conf);
assert_eq!(expected, result.unwrap());
}
#[test]
fn test_mixed_nodes() {
let xml = r#"<?xml version="1.0" encoding="utf-8"?><a attr1="val1">some text</a>"#;
let expected_1 = json!({
"a": {
"@attr1":"val1",
"#text":"some text"
}
});
let result_1 = xml_string_to_json(String::from(xml), &Config::new_with_defaults());
assert_eq!(expected_1, result_1.unwrap());
let expected_2 = json!({
"a": {
"attr1":"val1",
"text":"some text"
}
});
let conf = Config::new_with_custom_values(true, "", "text", NullValue::Null);
let result_2 = xml_string_to_json(String::from(xml), &conf);
assert_eq!(expected_2, result_2.unwrap());
let xml = r#"<?xml version="1.0" encoding="utf-8"?><a attr1="val1"><attr1><nested>some text</nested></attr1></a>"#;
let expected_3 = json!({"a":{"attr1":["val1",{"nested":"some text"}]}});
let result_3 = xml_string_to_json(String::from(xml), &conf);
assert_eq!(expected_3, result_3.unwrap());
}
#[cfg(feature = "json_types")]
#[test]
fn test_add_json_type_override() {
let config = Config::new_with_defaults()
.add_json_type_override("a/@attr1", JsonArray::Infer(JsonType::AlwaysString));
assert!(config.json_type_overrides.get("/a/@attr1").is_some());
let config = Config::new_with_defaults()
.add_json_type_override("/a/@attr1", JsonArray::Infer(JsonType::AlwaysString));
assert!(config.json_type_overrides.get("/a/@attr1").is_some());
}
#[cfg(feature = "json_types")]
#[test]
fn test_json_type_overrides() {
let xml = r#"<a attr1="007"><b attr1="7" attr2="True">true</b></a>"#;
let expected = json!({
"a": {
"@attr1":7,
"b": {
"@attr1":7,
"@attr2":"True",
"#text":true
}
}
});
let config = Config::new_with_defaults();
let result = xml_string_to_json(String::from(xml), &config);
assert_eq!(expected, result.unwrap());
let expected = json!({
"a": {
"@attr1":"007",
"b": {
"@attr1":7,
"@attr2":"True",
"#text":true
}
}
});
let conf = Config::new_with_defaults()
.add_json_type_override("/a/@attr1", JsonArray::Infer(JsonType::AlwaysString));
let result = xml_string_to_json(String::from(xml), &conf);
assert_eq!(expected, result.unwrap());
let expected = json!({
"a": {
"@attr1":"007",
"b": {
"@attr1":"7",
"@attr2":true,
"#text":true
}
}
});
let conf = Config::new_with_defaults()
.add_json_type_override("/a/@attr1", JsonArray::Infer(JsonType::AlwaysString))
.add_json_type_override("/a/b/@attr1", JsonArray::Infer(JsonType::AlwaysString))
.add_json_type_override(
"/a/b/@attr2",
JsonArray::Infer(JsonType::Bool(vec!["True"])),
);
let result = xml_string_to_json(String::from(xml), &conf);
assert_eq!(expected, result.unwrap());
let expected = json!({
"a": {
"@attr1":"007",
"b": {
"@attr1":"7",
"@attr2":"True",
"#text":"true"
}
}
});
let conf = Config::new_with_defaults()
.add_json_type_override("/a/@attr1", JsonArray::Infer(JsonType::AlwaysString))
.add_json_type_override("/a/b/@attr1", JsonArray::Infer(JsonType::AlwaysString))
.add_json_type_override("/a/b", JsonArray::Infer(JsonType::AlwaysString));
let result = xml_string_to_json(String::from(xml), &conf);
assert_eq!(expected, result.unwrap());
}
#[cfg(feature = "json_types")]
#[test]
fn test_enforce_array() {
let xml = r#"<a attr1="att1"><b c="att">1</b><b c="att">2</b></a>"#;
let expected = json!({
"a": {
"@attr1":"att1",
"b": [{ "@c":"att", "#text":1 }, { "@c":"att", "#text":2 }]
}
});
let config = Config::new_with_defaults();
let result = xml_string_to_json(String::from(xml), &config);
assert_eq!(expected, result.unwrap());
let xml = r#"<a attr1="att1"><b c="att">1</b></a>"#;
let expected = json!({
"a": {
"@attr1":"att1",
"b": { "@c":"att", "#text":1 }
}
});
let result = xml_string_to_json(String::from(xml), &config);
assert_eq!(expected, result.unwrap());
let xml = r#"<a attr1="att1"><b c="att">1</b></a>"#;
let expected = json!({
"a": {
"@attr1":"att1",
"b": [{ "@c":"att", "#text":1 }]
}
});
let config = Config::new_with_defaults()
.add_json_type_override("/a/b", JsonArray::Always(JsonType::Infer));
let result = xml_string_to_json(String::from(xml), &config);
assert_eq!(expected, result.unwrap());
let xml = r#"<a><b>1</b></a>"#;
let expected = json!({
"a": {
"b": [1]
}
});
let config = Config::new_with_defaults()
.add_json_type_override("/a/b", JsonArray::Always(JsonType::Infer));
let result = xml_string_to_json(String::from(xml), &config);
assert_eq!(expected, result.unwrap());
let xml = r#"<a><b>1</b><b>2</b></a>"#;
let expected = json!({
"a": {
"b": [1,2]
}
});
let config = Config::new_with_defaults()
.add_json_type_override("/a/b", JsonArray::Always(JsonType::Infer));
let result = xml_string_to_json(String::from(xml), &config);
assert_eq!(expected, result.unwrap());
let xml = r#"<a><b>1</b></a>"#;
let expected = json!({
"a": {
"b": ["1"]
}
});
let config = Config::new_with_defaults()
.add_json_type_override("/a/b", JsonArray::Always(JsonType::AlwaysString));
let result = xml_string_to_json(String::from(xml), &config);
assert_eq!(expected, result.unwrap());
let xml = r#"<a><b>1</b><b>2</b></a>"#;
let expected = json!({
"a": {
"b": ["1","2"]
}
});
let config = Config::new_with_defaults()
.add_json_type_override("/a/b", JsonArray::Always(JsonType::AlwaysString));
let result = xml_string_to_json(String::from(xml), &config);
assert_eq!(expected, result.unwrap());
let xml = r#"<a><b /></a>"#;
let expected = json!({
"a": {
"b": [null]
}
});
let config = Config::new_with_custom_values(false, "@", "#text", NullValue::Null)
.add_json_type_override("/a/b", JsonArray::Always(JsonType::Infer));
let result = xml_string_to_json(String::from(xml), &config);
assert_eq!(expected, result.unwrap());
}
#[test]
fn test_malformed_xml() {
let xml = r#"<?xml version="1.0" encoding="utf-8"?><a attr1="val1">some text<b></a>"#;
let result_1 = xml_string_to_json(String::from(xml), &Config::new_with_defaults());
assert!(result_1.is_err());
}
#[test]
fn test_parse_text() {
assert_eq!(0.0, parse_text("0.0", false, &JsonType::Infer));
assert_eq!(0, parse_text("0", false, &JsonType::Infer));
assert_eq!(0, parse_text("0000", false, &JsonType::Infer));
assert_eq!(0, parse_text("0", true, &JsonType::Infer));
assert_eq!("0000", parse_text("0000", true, &JsonType::Infer));
assert_eq!(0.42, parse_text("0.4200", false, &JsonType::Infer));
assert_eq!(142.42, parse_text("142.4200", false, &JsonType::Infer));
assert_eq!("0xAC", parse_text("0xAC", true, &JsonType::Infer));
assert_eq!("0x03", parse_text("0x03", true, &JsonType::Infer));
assert_eq!("142,4200", parse_text("142,4200", true, &JsonType::Infer));
assert_eq!("142,420,0", parse_text("142,420,0", true, &JsonType::Infer));
assert_eq!(
"142,420,0.0",
parse_text("142,420,0.0", true, &JsonType::Infer)
);
assert_eq!("0Test", parse_text("0Test", true, &JsonType::Infer));
assert_eq!("0.Test", parse_text("0.Test", true, &JsonType::Infer));
assert_eq!("0.22Test", parse_text("0.22Test", true, &JsonType::Infer));
assert_eq!("0044951", parse_text("0044951", true, &JsonType::Infer));
assert_eq!(1, parse_text("1", true, &JsonType::Infer));
assert_eq!(false, parse_text("false", false, &JsonType::Infer));
assert_eq!(true, parse_text("true", true, &JsonType::Infer));
assert_eq!("True", parse_text("True", true, &JsonType::Infer));
#[cfg(feature = "json_types")]
{
let bool_type = JsonType::Bool(vec!["true", "True", "", "1"]);
assert_eq!(false, parse_text("false", false, &bool_type));
assert_eq!(true, parse_text("true", false, &bool_type));
assert_eq!(true, parse_text("True", false, &bool_type));
assert_eq!(false, parse_text("TRUE", false, &bool_type));
assert_eq!(true, parse_text("", false, &bool_type));
assert_eq!(true, parse_text("1", false, &bool_type));
assert_eq!(false, parse_text("0", false, &bool_type));
assert_eq!(true, parse_text(" ", false, &bool_type));
}
assert_eq!("abc", parse_text("abc", false, &JsonType::AlwaysString));
assert_eq!("true", parse_text("true", false, &JsonType::AlwaysString));
assert_eq!("123", parse_text("123", false, &JsonType::AlwaysString));
assert_eq!("0123", parse_text("0123", false, &JsonType::AlwaysString));
assert_eq!(
"0.4200",
parse_text("0.4200", false, &JsonType::AlwaysString)
);
}
#[test]
fn convert_test_files() {
let mut entries = std::fs::read_dir("./test_xml_files")
.unwrap()
.map(|res| res.map(|e| e.path()))
.collect::<Result<Vec<_>, std::io::Error>>()
.unwrap();
entries.sort();
let conf = Config::new_with_custom_values(true, "", "text", NullValue::Null);
for mut entry in entries {
if entry.extension().unwrap() != "xml" {
continue;
}
let mut file = File::open(&entry).unwrap();
let mut xml_contents = String::new();
file.read_to_string(&mut xml_contents).unwrap();
let json = xml_string_to_json(xml_contents, &conf).unwrap();
entry.set_extension("json");
let mut file = File::create(&entry).unwrap();
assert!(
file.write_all(to_string_pretty(&json).unwrap().as_bytes())
.is_ok(),
"Failed on {:?}",
entry.as_os_str()
);
}
}
#[test]
fn test_xml_str_to_json() {
let expected = json!({
"a": {
"b":[ 12345, 12345.0, 12345.6 ]
}
});
let result = xml_str_to_json(
"<a><b>12345</b><b>12345.0</b><b>12345.6</b></a>",
&Config::new_with_defaults(),
);
assert_eq!(expected, result.unwrap());
}
#[cfg(feature = "regex_path")]
#[test]
fn test_regex_json_type_overrides() {
use regex::Regex;
let xml = r#"<a attr1="att1"><b c="att">1</b></a>"#;
let expected = json!({
"a": {
"@attr1":"att1",
"b": [{ "@c":"att", "#text":1 }]
}
});
let config = Config::new_with_defaults().add_json_type_override(
Regex::new(r"\w/b").unwrap(),
JsonArray::Always(JsonType::Infer),
);
let result = xml_string_to_json(String::from(xml), &config);
assert_eq!(expected, result.unwrap());
let xml = r#"
<a attr1="att1">
<element name="el1" />
<element name="el2" />
<b attr2="att2">
<element name="el3" />
<c attr3="att3">
<element name="el4" />
</c>
</b>
</a>
"#;
let expected = json!({
"a": {
"@attr1": "att1",
"element": [
{ "@name": "el1" },
{ "@name": "el2" }
],
"b": {
"@attr2": "att2",
"element": [
{ "@name": "el3" }
],
"c": {
"@attr3": "att3",
"element": [
{ "@name": "el4" }
]
}
},
}
});
let config = Config::new_with_defaults().add_json_type_override(
Regex::new(r"element").unwrap(),
JsonArray::Always(JsonType::Infer),
);
let result = xml_string_to_json(String::from(xml), &config);
assert_eq!(expected, result.unwrap());
}
#[test]
fn test_map_xml_to_json_per_child() {
let xml = r#"
<root>
<a><b>123</b></a>
<a><b>456</b></a>
</root>
"#;
let expected = vec![
(String::from("<a><b>123</b></a>"), json!({"a": { "b": 123}})),
(String::from("<a><b>456</b></a>"), json!({"a": { "b": 456}})),
];
let result = map_xml_to_json_per_child(String::from(xml), &Config::new_with_defaults());
assert_eq!(expected, result.unwrap());
}