serde_xml_rs/
lib.rs

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;
53//! use serde_derive::{Deserialize, Serialize};
54//! use serde_xml_rs::{from_str, to_string};
55//!
56//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
57//! struct Item {
58//!     name: String,
59//!     source: String,
60//! }
61//!
62//! fn main() {
63//!     let src = r#"<Item><name>Banana</name><source>Store</source></Item>"#;
64//!     let should_be = Item {
65//!         name: "Banana".to_string(),
66//!         source: "Store".to_string(),
67//!     };
68//!
69//!     let item: Item = from_str(src).unwrap();
70//!     assert_eq!(item, should_be);
71//!
72//!     let reserialized_item = to_string(&item).unwrap();
73//!     assert_eq!(src, reserialized_item);
74//! }
75//! ```
76//!
77//! ## Tag contents
78//!
79//! ```rust
80//! # use serde;
81//! # use serde_derive::{Deserialize, Serialize};
82//! # use serde_xml_rs::{from_str, to_string};
83//!
84//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
85//! struct Document {
86//!     content: Content
87//! }
88//!
89//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
90//! struct Content {
91//!     #[serde(rename = "$value")]
92//!     value: String
93//! }
94//!
95//! fn main() {
96//!     let src = r#"<document><content>Lorem ipsum</content></document>"#;
97//!     let document: Document = from_str(src).unwrap();
98//!     assert_eq!(document.content.value, "Lorem ipsum");
99//! }
100//! ```
101//!
102//! ## Repeated tags
103//!
104//! ```rust
105//! # use serde;
106//! # use serde_derive::{Deserialize, Serialize};
107//! # use serde_xml_rs::{from_str, to_string};
108//!
109//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
110//! struct PlateAppearance {
111//!     #[serde(rename = "$value")]
112//!     events: Vec<Event>
113//! }
114//!
115//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
116//! #[serde(rename_all = "kebab-case")]
117//! enum Event {
118//!     Pitch(Pitch),
119//!     Runner(Runner),
120//! }
121//!
122//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
123//! struct Pitch {
124//!     speed: u32,
125//!     r#type: PitchType,
126//!     outcome: PitchOutcome,
127//! }
128//!
129//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
130//! enum PitchType { FourSeam, TwoSeam, Changeup, Cutter, Curve, Slider, Knuckle, Pitchout }
131//!
132//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
133//! enum PitchOutcome { Ball, Strike, Hit }
134//!
135//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
136//! struct Runner {
137//!     from: Base, to: Option<Base>, outcome: RunnerOutcome,
138//! }
139//!
140//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
141//! enum Base { First, Second, Third, Home }
142//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
143//! enum RunnerOutcome { Steal, Caught, PickOff }
144//!
145//! fn main() {
146//!     let document = r#"
147//!         <plate-appearance>
148//!           <pitch speed="95" type="FourSeam" outcome="Ball" />
149//!           <pitch speed="91" type="FourSeam" outcome="Strike" />
150//!           <pitch speed="85" type="Changeup" outcome="Ball" />
151//!           <runner from="First" to="Second" outcome="Steal" />
152//!           <pitch speed="89" type="Slider" outcome="Strike" />
153//!           <pitch speed="88" type="Curve" outcome="Hit" />
154//!         </plate-appearance>"#;
155//!     let plate_appearance: PlateAppearance = from_str(document).unwrap();
156//!     assert_eq!(plate_appearance.events[0], Event::Pitch(Pitch { speed: 95, r#type: PitchType::FourSeam, outcome: PitchOutcome::Ball }));
157//! }
158//! ```
159//!
160//! ## Custom EventReader
161//!
162//! ```rust
163//! use serde::Deserialize;
164//! use serde_derive::{Deserialize, Serialize};
165//! use serde_xml_rs::{from_str, to_string, de::Deserializer};
166//! use xml::reader::{EventReader, ParserConfig};
167//!
168//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
169//! struct Item {
170//!     name: String,
171//!     source: String,
172//! }
173//!
174//! fn main() {
175//!     let src = r#"<Item><name>  Banana  </name><source>Store</source></Item>"#;
176//!     let should_be = Item {
177//!         name: "  Banana  ".to_string(),
178//!         source: "Store".to_string(),
179//!     };
180//!
181//!     let config = ParserConfig::new()
182//!         .trim_whitespace(false)
183//!         .whitespace_to_characters(true);
184//!     let event_reader = EventReader::new_with_config(src.as_bytes(), config);
185//!     let item = Item::deserialize(&mut Deserializer::new(event_reader)).unwrap();
186//!     assert_eq!(item, should_be);
187//! }
188//! ```
189//!
190
191pub mod de;
192mod error;
193pub mod ser;
194
195pub use crate::de::{from_reader, from_str, Deserializer};
196pub use crate::error::Error;
197pub use crate::ser::{to_string, to_writer, Serializer};
198pub use xml::reader::{EventReader, ParserConfig};