//! # Serde XML //! //! XML is a flexible markup language that is still used for sharing data between applications or //! for writing configuration files. //! //! Serde XML provides a way to convert between text and strongly-typed Rust data structures. //! //! ## Caveats //! //! The Serde framework was mainly designed with formats such as JSON or YAML in mind. //! As opposed to XML, these formats have the advantage of a stricter syntax which makes it //! possible to know what type a field is without relying on an accompanying schema, //! and disallows repeating the same tag multiple times in the same object. //! //! For example, encoding the following document in YAML is not trivial. //! //! ```xml //! //!
A header
//!
First section
//!
Second section
//! A sidenote //!
Third section
//! Another sidenote //!
Fourth section
//! //!
//! ``` //! //! One possibility is the following YAML document. //! //! ```yaml //! - header: A header //! - section: First section //! - section: Second section //! - sidenote: A sidenote //! - section: Third section //! - sidenote: Another sidenote //! - section: Fourth section //! - footer: The footer //! ``` //! //! Other notable differences: //! - XML requires a named root node. //! - XML has a namespace system. //! - XML distinguishes between attributes, child tags and contents. //! - In XML, the order of nodes is sometimes important. //! //! ## Basic example //! //! ```rust //! use serde::{Deserialize, Serialize}; //! use serde_xml_rs::{from_str, to_string}; //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! struct Item { //! name: String, //! source: String, //! } //! //! fn main() { //! let src = r#"BananaStore"#; //! let should_be = Item { //! name: "Banana".to_string(), //! source: "Store".to_string(), //! }; //! //! let item: Item = from_str(src).unwrap(); //! assert_eq!(item, should_be); //! //! let reserialized_item = to_string(&item).unwrap(); //! assert_eq!(src, reserialized_item); //! } //! ``` //! //! ## Tag contents //! //! ```rust //! # use serde::{Deserialize, Serialize}; //! # use serde_xml_rs::{from_str, to_string}; //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! struct Document { //! content: Content //! } //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! struct Content { //! #[serde(rename = "$value")] //! value: String //! } //! //! fn main() { //! let src = r#"Lorem ipsum"#; //! let document: Document = from_str(src).unwrap(); //! assert_eq!(document.content.value, "Lorem ipsum"); //! } //! ``` //! //! ## Repeated tags //! //! ```rust //! # use serde::{Deserialize, Serialize}; //! # use serde_xml_rs::{from_str, to_string}; //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! struct PlateAppearance { //! #[serde(rename = "$value")] //! events: Vec //! } //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! #[serde(rename_all = "kebab-case")] //! enum Event { //! Pitch(Pitch), //! Runner(Runner), //! } //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! struct Pitch { //! speed: u32, //! r#type: PitchType, //! outcome: PitchOutcome, //! } //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! enum PitchType { FourSeam, TwoSeam, Changeup, Cutter, Curve, Slider, Knuckle, Pitchout } //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! enum PitchOutcome { Ball, Strike, Hit } //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! struct Runner { //! from: Base, to: Option, outcome: RunnerOutcome, //! } //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! enum Base { First, Second, Third, Home } //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! enum RunnerOutcome { Steal, Caught, PickOff } //! //! fn main() { //! let document = r#" //! //! //! //! //! //! //! //! "#; //! let plate_appearance: PlateAppearance = from_str(document).unwrap(); //! assert_eq!(plate_appearance.events[0], Event::Pitch(Pitch { speed: 95, r#type: PitchType::FourSeam, outcome: PitchOutcome::Ball })); //! } //! ``` //! //! ## Custom EventReader //! //! ```rust //! use serde::{Deserialize, Serialize}; //! use serde_xml_rs::{from_str, to_string, de::Deserializer}; //! use xml::reader::{EventReader, ParserConfig}; //! //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! struct Item { //! name: String, //! source: String, //! } //! //! fn main() { //! let src = r#" Banana Store"#; //! let should_be = Item { //! name: " Banana ".to_string(), //! source: "Store".to_string(), //! }; //! //! let config = ParserConfig::new() //! .trim_whitespace(false) //! .whitespace_to_characters(true); //! let event_reader = EventReader::new_with_config(src.as_bytes(), config); //! let item = Item::deserialize(&mut Deserializer::new(event_reader)).unwrap(); //! assert_eq!(item, should_be); //! } //! ``` //! pub mod de; mod error; pub mod ser; pub use crate::de::{from_reader, from_str, Deserializer}; pub use crate::error::Error; pub use crate::ser::{to_string, to_writer, Serializer}; pub use xml::reader::{EventReader, ParserConfig};