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};