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::{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
187pub mod de;
188mod error;
189pub mod ser;
190
191pub use crate::de::{from_reader, from_str, Deserializer};
192pub use crate::error::Error;
193pub use crate::ser::{to_string, to_writer, Serializer};
194pub use xml::reader::{EventReader, ParserConfig};