serde_xml_rs/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
//! # 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
//! <document>
//!   <header>A header</header>
//!   <section>First section</section>
//!   <section>Second section</section>
//!   <sidenote>A sidenote</sidenote>
//!   <section>Third section</section>
//!   <sidenote>Another sidenote</sidenote>
//!   <section>Fourth section</section>
//!   <footer>The footer</footer>
//! </document>
//! ```
//!
//! 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;
//! use serde_derive::{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#"<Item><name>Banana</name><source>Store</source></Item>"#;
//!     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;
//! # use serde_derive::{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#"<document><content>Lorem ipsum</content></document>"#;
//!     let document: Document = from_str(src).unwrap();
//!     assert_eq!(document.content.value, "Lorem ipsum");
//! }
//! ```
//!
//! ## Repeated tags
//!
//! ```rust
//! # use serde;
//! # use serde_derive::{Deserialize, Serialize};
//! # use serde_xml_rs::{from_str, to_string};
//!
//! #[derive(Debug, Serialize, Deserialize, PartialEq)]
//! struct PlateAppearance {
//!     #[serde(rename = "$value")]
//!     events: Vec<Event>
//! }
//!
//! #[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<Base>, 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#"
//!         <plate-appearance>
//!           <pitch speed="95" type="FourSeam" outcome="Ball" />
//!           <pitch speed="91" type="FourSeam" outcome="Strike" />
//!           <pitch speed="85" type="Changeup" outcome="Ball" />
//!           <runner from="First" to="Second" outcome="Steal" />
//!           <pitch speed="89" type="Slider" outcome="Strike" />
//!           <pitch speed="88" type="Curve" outcome="Hit" />
//!         </plate-appearance>"#;
//!     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;
//! use serde_derive::{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#"<Item><name>  Banana  </name><source>Store</source></Item>"#;
//!     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};