#[macro_use]
extern crate log;
mod element;
mod encoding;
mod necessity;
mod options;
mod parser;
pub use element::Element;
pub use encoding::{convert_to_utf8, detect_encoding, read_file_as_utf8, EncodingError};
pub use necessity::{merge_necessity, Necessity};
pub use options::{Options, SortBy};
pub use parser::{extend_struct, into_struct, ParserError};
#[cfg(test)]
mod tests {
use crate::{into_struct, Options};
use pretty_assertions::assert_eq;
use quick_xml::reader::Reader;
#[test]
fn parse_xml_and_return_struct_as_str() {
let xml = "<a b=\"c\">d</a>";
let mut reader = Reader::from_str(xml);
let root = into_struct(&mut reader).expect("expected to successfully parse into struct");
let expected = "\
#[derive(Serialize, Deserialize)]
pub struct A {
#[serde(rename = \"@b\")]
pub b: String,
#[serde(rename = \"$text\")]
pub text: Option<String>,
}
";
assert_eq!(expected, root.to_serde_struct(&Options::quick_xml_de()));
}
#[test]
fn parse_xml_and_return_shallow_nested_duplicate_struct_as_str() {
let xml = "<a><a></a></a>";
let mut reader = Reader::from_str(xml);
let root = into_struct(&mut reader).expect("expected to successfully parse into struct");
let expected = "\
#[derive(Serialize, Deserialize)]
pub struct A {
pub a: AA,
}
#[derive(Serialize, Deserialize)]
pub struct AA {
}
";
assert_eq!(expected, root.to_serde_struct(&Options::quick_xml_de()));
}
#[test]
fn parse_xml_and_return_deep_nested_duplicate_struct_as_str() {
let xml = "<a><b><c><d><e><a></a></e></d></c></b></a>";
let mut reader = Reader::from_str(xml);
let root = into_struct(&mut reader).expect("expected to successfully parse into struct");
let expected = "\
#[derive(Serialize, Deserialize)]
pub struct A {
pub b: B,
}
#[derive(Serialize, Deserialize)]
pub struct B {
pub c: C,
}
#[derive(Serialize, Deserialize)]
pub struct C {
pub d: D,
}
#[derive(Serialize, Deserialize)]
pub struct D {
pub e: E,
}
#[derive(Serialize, Deserialize)]
pub struct E {
pub a: ABCDEA,
}
#[derive(Serialize, Deserialize)]
pub struct ABCDEA {
}
";
assert_eq!(expected, root.to_serde_struct(&Options::quick_xml_de()));
}
#[test]
fn parse_multiple_children_as_vec() {
let xml = "<a><b>asd</b><b>fgh</b></a>";
let mut reader = Reader::from_str(xml);
let root = into_struct(&mut reader).expect("expected to successfully parse into struct");
let expected = "\
#[derive(Serialize, Deserialize)]
pub struct A {
pub b: Vec<String>,
}
";
assert_eq!(expected, root.to_serde_struct(&Options::quick_xml_de()));
}
#[test]
fn parse_multiple_optional_children() {
let xml = "<a><b><id>1</id></b><b><id>2</id><c>1</c><c>1</c></b></a>";
let mut reader = Reader::from_str(xml);
let root = into_struct(&mut reader).expect("expected to successfully parse into struct");
let expected = "\
#[derive(Serialize, Deserialize)]
pub struct A {
pub b: Vec<B>,
}
#[derive(Serialize, Deserialize)]
pub struct B {
pub id: String,
pub c: Option<Vec<String>>,
}
";
assert_eq!(expected, root.to_serde_struct(&Options::quick_xml_de()));
}
#[test]
fn create_struct_names_as_pascal_case() {
let xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<?xml-stylesheet type=\"text/xsl\" href=\"redacted.xsl\"?>
<MVCI_MODULE_DESCRIPTION>
<PINTYPE>
<ID>0</ID>
</PINTYPE>
</MVCI_MODULE_DESCRIPTION>";
let mut reader = Reader::from_str(xml);
let root = into_struct(&mut reader).expect("expected to successfully parse into struct");
let expected = "\
#[derive(Serialize, Deserialize)]
pub struct MvciModuleDescription {
#[serde(rename = \"$text\")]
pub text: Option<String>,
#[serde(rename = \"PINTYPE\")]
pub pintype: Pintype,
}
#[derive(Serialize, Deserialize)]
pub struct Pintype {
#[serde(rename = \"$text\")]
pub text: Option<String>,
#[serde(rename = \"ID\")]
pub id: String,
}
";
assert_eq!(expected, root.to_serde_struct(&Options::quick_xml_de()));
}
#[test]
fn remove_namespace_prefix() {
let xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<OTA_Rate xmlns=\"http://www.opentravel.org/OTA/2003/05\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xsi:schemaLocation=\"http://www.opentravel.org/OTA/2003/05 OTA_Rate.xsd\">
<Success />
</OTA_Rate>";
let mut reader = Reader::from_str(xml);
let root = into_struct(&mut reader).expect("expected to successfully parse into struct");
let expected = "\
#[derive(Serialize, Deserialize)]
pub struct OtaRate {
#[serde(rename = \"@xmlns\")]
pub xmlns: String,
#[serde(rename = \"@xmlns:xsi\")]
pub xmlns_xsi: String,
#[serde(rename = \"@schemaLocation\")]
pub xsi_schema_location: String,
#[serde(rename = \"$text\")]
pub text: Option<String>,
#[serde(rename = \"Success\")]
pub success: Success,
}
#[derive(Serialize, Deserialize)]
pub struct Success {
}
";
assert_eq!(expected, root.to_serde_struct(&Options::quick_xml_de()));
}
#[test]
fn handle_duplicate_children_correctly() {
let xml = "
<UpsellCandidate>
<DailyPriceDiff>
<Amount xmlns=\"\">0.63</Amount>
<Currency xmlns=\"\">EUR</Currency>
</DailyPriceDiff>
<TotalPriceDiff>
<Amount xmlns=\"\">4.43</Amount>
<Currency xmlns=\"\">EUR</Currency>
</TotalPriceDiff>
</UpsellCandidate>";
let mut reader = Reader::from_str(xml);
let root = into_struct(&mut reader).expect("expected to successfully parse into struct");
let expected = "\
#[derive(Serialize, Deserialize)]
pub struct UpsellCandidate {
#[serde(rename = \"$text\")]
pub text: Option<String>,
#[serde(rename = \"DailyPriceDiff\")]
pub daily_price_diff: DailyPriceDiff,
#[serde(rename = \"TotalPriceDiff\")]
pub total_price_diff: TotalPriceDiff,
}
#[derive(Serialize, Deserialize)]
pub struct DailyPriceDiff {
#[serde(rename = \"$text\")]
pub text: Option<String>,
#[serde(rename = \"Amount\")]
pub amount: DailyPriceDiffAmount,
#[serde(rename = \"Currency\")]
pub currency: DailyPriceDiffCurrency,
}
#[derive(Serialize, Deserialize)]
pub struct DailyPriceDiffAmount {
#[serde(rename = \"@xmlns\")]
pub xmlns: String,
#[serde(rename = \"$text\")]
pub text: Option<String>,
}
#[derive(Serialize, Deserialize)]
pub struct DailyPriceDiffCurrency {
#[serde(rename = \"@xmlns\")]
pub xmlns: String,
#[serde(rename = \"$text\")]
pub text: Option<String>,
}
#[derive(Serialize, Deserialize)]
pub struct TotalPriceDiff {
#[serde(rename = \"$text\")]
pub text: Option<String>,
#[serde(rename = \"Amount\")]
pub amount: TotalPriceDiffAmount,
#[serde(rename = \"Currency\")]
pub currency: TotalPriceDiffCurrency,
}
#[derive(Serialize, Deserialize)]
pub struct TotalPriceDiffAmount {
#[serde(rename = \"@xmlns\")]
pub xmlns: String,
#[serde(rename = \"$text\")]
pub text: Option<String>,
}
#[derive(Serialize, Deserialize)]
pub struct TotalPriceDiffCurrency {
#[serde(rename = \"@xmlns\")]
pub xmlns: String,
#[serde(rename = \"$text\")]
pub text: Option<String>,
}
";
assert_eq!(expected, root.to_serde_struct(&Options::quick_xml_de()));
}
#[test]
fn parse_xml_and_return_struct_with_cyrillic_variables() {
let xml = "\
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<КоммерческаяИнформация>
<Классификатор>
<Ид>1</Ид>
<Наименование>Классификатор</Наименование>
<Владелец>Булат</Владелец>
</Классификатор>
</КоммерческаяИнформация>";
let mut reader = Reader::from_str(xml);
let root = into_struct(&mut reader).expect("expected to successfully parse into struct");
let expected = "\
#[derive(Serialize, Deserialize)]
pub struct КоммерческаяИнформация {
#[serde(rename = \"$text\")]
pub text: Option<String>,
#[serde(rename = \"Классификатор\")]
pub классификатор: Классификатор,
}
#[derive(Serialize, Deserialize)]
pub struct Классификатор {
#[serde(rename = \"$text\")]
pub text: Option<String>,
#[serde(rename = \"Ид\")]
pub ид: String,
#[serde(rename = \"Наименование\")]
pub наименование: String,
#[serde(rename = \"Владелец\")]
pub владелец: String,
}
";
assert_eq!(expected, root.to_serde_struct(&Options::quick_xml_de()));
}
#[test]
fn preserve_document_order() {
let xml = "<doc>
<comment>A comment.</comment>
<sentence>This is the first sentence.</sentence>
<break/>
<sentence>This is the second sentence.</sentence>
<sentence>This is the third sentence.</sentence>
<comment>Another comment.</comment>
</doc>";
let mut reader = Reader::from_str(xml);
let root = into_struct(&mut reader).expect("expected to successfully parse into struct");
let expected = "\
#[derive(Serialize, Deserialize)]
pub struct Doc {
#[serde(rename = \"$text\")]
pub text: Option<String>,
pub comment: Vec<String>,
pub sentence: Vec<String>,
#[serde(rename = \"break\")]
pub doc_break: Break,
}
#[derive(Serialize, Deserialize)]
pub struct Break {
}
";
assert_eq!(expected, root.to_serde_struct(&Options::quick_xml_de()));
}
#[test]
fn preserve_document_order_for_attributes() {
let xml = "<doc>
<a b=\"b\" c=\"c\">a</a>
<a b=\"b\">a</a>
<a c=\"c\" d=\"d\" b=\"b\" >a</a>
</doc>";
let mut reader = Reader::from_str(xml);
let root = into_struct(&mut reader).expect("expected to successfully parse into struct");
let expected = "\
#[derive(Serialize, Deserialize)]
pub struct Doc {
#[serde(rename = \"$text\")]
pub text: Option<String>,
pub a: Vec<A>,
}
#[derive(Serialize, Deserialize)]
pub struct A {
#[serde(rename = \"@b\")]
pub b: String,
#[serde(rename = \"@c\")]
pub c: Option<String>,
#[serde(rename = \"@d\")]
pub d: Option<String>,
#[serde(rename = \"$text\")]
pub text: Option<String>,
}
";
assert_eq!(expected, root.to_serde_struct(&Options::quick_xml_de()));
}
}