1 //! # Serde XML 2 //! 3 //! XML is a flexible markup language that is still used for sharing data between applications or 4 //! for writing configuration files. 5 //! 6 //! Serde XML provides a way to convert between text and strongly-typed Rust data structures. 7 //! 8 //! ## Caveats 9 //! 10 //! The Serde framework was mainly designed with formats such as JSON or YAML in mind. 11 //! As opposed to XML, these formats have the advantage of a stricter syntax which makes it 12 //! possible to know what type a field is without relying on an accompanying schema, 13 //! and disallows repeating the same tag multiple times in the same object. 14 //! 15 //! For example, encoding the following document in YAML is not trivial. 16 //! 17 //! ```xml 18 //! <document> 19 //! <header>A header</header> 20 //! <section>First section</section> 21 //! <section>Second section</section> 22 //! <sidenote>A sidenote</sidenote> 23 //! <section>Third section</section> 24 //! <sidenote>Another sidenote</sidenote> 25 //! <section>Fourth section</section> 26 //! <footer>The footer</footer> 27 //! </document> 28 //! ``` 29 //! 30 //! One possibility is the following YAML document. 31 //! 32 //! ```yaml 33 //! - header: A header 34 //! - section: First section 35 //! - section: Second section 36 //! - sidenote: A sidenote 37 //! - section: Third section 38 //! - sidenote: Another sidenote 39 //! - section: Fourth section 40 //! - footer: The footer 41 //! ``` 42 //! 43 //! Other notable differences: 44 //! - XML requires a named root node. 45 //! - XML has a namespace system. 46 //! - XML distinguishes between attributes, child tags and contents. 47 //! - In XML, the order of nodes is sometimes important. 48 //! 49 //! ## Basic example 50 //! 51 //! ```rust 52 //! use serde::{Deserialize, Serialize}; 53 //! use serde_xml_rs::{from_str, to_string}; 54 //! 55 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 56 //! struct Item { 57 //! name: String, 58 //! source: String, 59 //! } 60 //! 61 //! fn main() { 62 //! let src = r#"<?xml version="1.0" encoding="UTF-8"?><Item><name>Banana</name><source>Store</source></Item>"#; 63 //! let should_be = Item { 64 //! name: "Banana".to_string(), 65 //! source: "Store".to_string(), 66 //! }; 67 //! 68 //! let item: Item = from_str(src).unwrap(); 69 //! assert_eq!(item, should_be); 70 //! 71 //! let reserialized_item = to_string(&item).unwrap(); 72 //! assert_eq!(src, reserialized_item); 73 //! } 74 //! ``` 75 //! 76 //! ## Tag contents 77 //! 78 //! ```rust 79 //! # use serde::{Deserialize, Serialize}; 80 //! # use serde_xml_rs::{from_str, to_string}; 81 //! 82 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 83 //! struct Document { 84 //! content: Content 85 //! } 86 //! 87 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 88 //! struct Content { 89 //! #[serde(rename = "$value")] 90 //! value: String 91 //! } 92 //! 93 //! fn main() { 94 //! let src = r#"<document><content>Lorem ipsum</content></document>"#; 95 //! let document: Document = from_str(src).unwrap(); 96 //! assert_eq!(document.content.value, "Lorem ipsum"); 97 //! } 98 //! ``` 99 //! 100 //! ## Repeated tags 101 //! 102 //! ```rust 103 //! # use serde::{Deserialize, Serialize}; 104 //! # use serde_xml_rs::{from_str, to_string}; 105 //! 106 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 107 //! struct PlateAppearance { 108 //! #[serde(rename = "$value")] 109 //! events: Vec<Event> 110 //! } 111 //! 112 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 113 //! #[serde(rename_all = "kebab-case")] 114 //! enum Event { 115 //! Pitch(Pitch), 116 //! Runner(Runner), 117 //! } 118 //! 119 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 120 //! struct Pitch { 121 //! speed: u32, 122 //! r#type: PitchType, 123 //! outcome: PitchOutcome, 124 //! } 125 //! 126 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 127 //! enum PitchType { FourSeam, TwoSeam, Changeup, Cutter, Curve, Slider, Knuckle, Pitchout } 128 //! 129 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 130 //! enum PitchOutcome { Ball, Strike, Hit } 131 //! 132 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 133 //! struct Runner { 134 //! from: Base, to: Option<Base>, outcome: RunnerOutcome, 135 //! } 136 //! 137 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 138 //! enum Base { First, Second, Third, Home } 139 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 140 //! enum RunnerOutcome { Steal, Caught, PickOff } 141 //! 142 //! fn main() { 143 //! let document = r#" 144 //! <plate-appearance> 145 //! <pitch speed="95" type="FourSeam" outcome="Ball" /> 146 //! <pitch speed="91" type="FourSeam" outcome="Strike" /> 147 //! <pitch speed="85" type="Changeup" outcome="Ball" /> 148 //! <runner from="First" to="Second" outcome="Steal" /> 149 //! <pitch speed="89" type="Slider" outcome="Strike" /> 150 //! <pitch speed="88" type="Curve" outcome="Hit" /> 151 //! </plate-appearance>"#; 152 //! let plate_appearance: PlateAppearance = from_str(document).unwrap(); 153 //! assert_eq!(plate_appearance.events[0], Event::Pitch(Pitch { speed: 95, r#type: PitchType::FourSeam, outcome: PitchOutcome::Ball })); 154 //! } 155 //! ``` 156 //! 157 //! ## Custom EventReader 158 //! 159 //! ```rust 160 //! use serde::{Deserialize, Serialize}; 161 //! use serde_xml_rs::{from_str, to_string, de::Deserializer}; 162 //! use xml::reader::{EventReader, ParserConfig}; 163 //! 164 //! #[derive(Debug, Serialize, Deserialize, PartialEq)] 165 //! struct Item { 166 //! name: String, 167 //! source: String, 168 //! } 169 //! 170 //! fn main() { 171 //! let src = r#"<Item><name> Banana </name><source>Store</source></Item>"#; 172 //! let should_be = Item { 173 //! name: " Banana ".to_string(), 174 //! source: "Store".to_string(), 175 //! }; 176 //! 177 //! let config = ParserConfig::new() 178 //! .trim_whitespace(false) 179 //! .whitespace_to_characters(true); 180 //! let event_reader = EventReader::new_with_config(src.as_bytes(), config); 181 //! let item = Item::deserialize(&mut Deserializer::new(event_reader)).unwrap(); 182 //! assert_eq!(item, should_be); 183 //! } 184 //! ``` 185 //! 186 187 pub mod de; 188 mod error; 189 pub mod ser; 190 191 pub use crate::de::{from_reader, from_str, Deserializer}; 192 pub use crate::error::Error; 193 pub use crate::ser::{to_string, to_writer, Serializer}; 194 pub use xml::reader::{EventReader, ParserConfig}; 195