use serde::{Serialize, Deserialize};
use quick_xml::se::to_string_with_config;
use quick_xml::de::from_str;
use quick_xml::se::Config;
// Plant will be mapped to XML. Field attributes contain directives for the
// serializer and deserializer. Here we use some special features
// of the quick-xml crate: the `rename` attribute dictates
// the name of the XML element representing this struct;
// `attribute` means that the `id` field is an XML
// *attribute* rather than a nested element.
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename = "plant")]
struct Plant {
#[serde(rename = "@id")]
id: i32,
name: String,
origin: Vec<String>,
}
impl std::fmt::Display for Plant {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Plant id={}, name={}, origin={:?}",
self.id, self.name, self.origin)
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut coffee = Plant {
id: 27,
name: "Coffee".to_string(),
origin: vec!["Ethiopia".to_string(), "Brazil".to_string()],
};
// Emit XML representing our plant; using
// to_string_with_config to produce a more
// human-readable output.
let config = Config::new().indent(' ', 2);
let out = to_string_with_config(&coffee, config)?;
println!("{}", out);
// To add a generic XML header to the output, prepend
// it explicitly.
println!("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n{}", out);
// Use from_str to parse a string of XML
// into a data structure. If the XML is malformed or
// cannot be mapped onto Plant, a descriptive error
// will be returned.
let p: Plant = from_str(&out)?;
println!("{}", p);
let tomato = Plant {
id: 81,
name: "Tomato".to_string(),
origin: vec!["Mexico".to_string(), "California".to_string()],
};
// The `rename` attribute on Nesting tells the serializer
// to nest all `plant`s under `<parent><child>...</child></parent>`
#[derive(Serialize)]
#[serde(rename = "nesting")]
struct Nesting {
#[serde(rename = "parent")]
parent: Parent,
}
#[derive(Serialize)]
struct Parent {
#[serde(rename = "child")]
child: Child,
}
#[derive(Serialize)]
struct Child {
plant: Vec<Plant>,
}
let nesting = Nesting {
parent: Parent {
child: Child {
plant: vec![coffee, tomato],
},
},
};
let out = to_string_with_config(&nesting, config)?;
println!("{}", out);
Ok(())
}