strong_xml/lib.rs
1//! Strong typed xml, based on xmlparser.
2//!
3//! [](https://github.com/PoiScript/strong-xml/actions?query=workflow%3ATest)
4//! [](https://crates.io/crates/strong-xml)
5//! [](https://docs.rs/strong-xml)
6//!
7//! ## Quick Start
8//!
9//! ```toml
10//! strong-xml = "0.6"
11//! ```
12//!
13//! ```rust
14//! use std::borrow::Cow;
15//! use strong_xml::{XmlRead, XmlWrite};
16//!
17//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
18//! #[xml(tag = "parent")]
19//! struct Parent<'a> {
20//! #[xml(attr = "attr1")]
21//! attr1: Cow<'a, str>,
22//! #[xml(attr = "attr2")]
23//! attr2: Option<Cow<'a, str>>,
24//! #[xml(child = "child")]
25//! child: Vec<Child<'a>>,
26//! }
27//!
28//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
29//! #[xml(tag = "child")]
30//! struct Child<'a> {
31//! #[xml(text)]
32//! text: Cow<'a, str>,
33//! }
34//!
35//! assert_eq!(
36//! (Parent { attr1: "val".into(), attr2: None, child: vec![] }).to_string().unwrap(),
37//! r#"<parent attr1="val"/>"#
38//! );
39//!
40//! assert_eq!(
41//! Parent::from_str(r#"<parent attr1="val" attr2="val"><child></child></parent>"#).unwrap(),
42//! Parent { attr1: "val".into(), attr2: Some("val".into()), child: vec![Child { text: "".into() }] }
43//! );
44//! ```
45//!
46//! ## Attributes
47//!
48//! ### `#[xml(tag = "")]`
49//!
50//! Specifies the xml tag of a struct or an enum variant.
51//!
52//! ```rust
53//! # use strong_xml::{XmlRead, XmlWrite};
54//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
55//! #[xml(tag = "parent")]
56//! struct Parent {}
57//!
58//! assert_eq!(
59//! (Parent {}).to_string().unwrap(),
60//! r#"<parent/>"#
61//! );
62//!
63//! assert_eq!(
64//! Parent::from_str(r#"<parent/>"#).unwrap(),
65//! Parent {}
66//! );
67//! ```
68//!
69//! ```rust
70//! # use strong_xml::{XmlRead, XmlWrite};
71//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
72//! #[xml(tag = "tag1")]
73//! struct Tag1 {}
74//!
75//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
76//! #[xml(tag = "tag2")]
77//! struct Tag2 {}
78//!
79//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
80//! enum Tag {
81//! #[xml(tag = "tag1")]
82//! Tag1(Tag1),
83//! #[xml(tag = "tag2")]
84//! Tag2(Tag2),
85//! }
86//!
87//! assert_eq!(
88//! (Tag::Tag1(Tag1 {})).to_string().unwrap(),
89//! r#"<tag1/>"#
90//! );
91//!
92//! assert_eq!(
93//! Tag::from_str(r#"<tag2></tag2>"#).unwrap(),
94//! Tag::Tag2(Tag2 {})
95//! );
96//! ```
97//!
98//! ### `#[xml(attr = "")]`
99//!
100//! Specifies that a struct field is attribute. Support
101//! `Cow<str>`, `Option<Cow<str>>`, `T` and `Option<T>`
102//! where `T: FromStr + Display`.
103//!
104//! ```rust
105//! use strong_xml::{XmlRead, XmlWrite};
106//!
107//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
108//! #[xml(tag = "parent")]
109//! struct Parent {
110//! #[xml(attr = "attr")]
111//! attr: usize
112//! }
113//!
114//! assert_eq!(
115//! (Parent { attr: 42 }).to_string().unwrap(),
116//! r#"<parent attr="42"/>"#
117//! );
118//!
119//! assert_eq!(
120//! Parent::from_str(r#"<parent attr="48"></parent>"#).unwrap(),
121//! Parent { attr: 48 }
122//! );
123//! ```
124//!
125//! ### `#[xml(child = "")]`
126//!
127//! Specifies that a struct field is a child element. Support
128//! `T`, `Option<T>`, `Vec<T>` where `T: XmlRead + XmlWrite`.
129//!
130//! ```rust
131//! use strong_xml::{XmlRead, XmlWrite};
132//!
133//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
134//! #[xml(tag = "tag1")]
135//! struct Tag1 {}
136//!
137//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
138//! #[xml(tag = "tag2")]
139//! struct Tag2 {}
140//!
141//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
142//! #[xml(tag = "tag3")]
143//! struct Tag3 {}
144//!
145//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
146//! enum Tag12 {
147//! #[xml(tag = "tag1")]
148//! Tag1(Tag1),
149//! #[xml(tag = "tag2")]
150//! Tag2(Tag2),
151//! }
152//!
153//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
154//! #[xml(tag = "parent")]
155//! struct Parent {
156//! #[xml(child = "tag3")]
157//! tag3: Vec<Tag3>,
158//! #[xml(child = "tag1", child = "tag2")]
159//! tag12: Option<Tag12>
160//! }
161//!
162//! assert_eq!(
163//! (Parent { tag3: vec![Tag3 {}], tag12: None }).to_string().unwrap(),
164//! r#"<parent><tag3/></parent>"#
165//! );
166//!
167//! assert_eq!(
168//! Parent::from_str(r#"<parent><tag2></tag2></parent>"#).unwrap(),
169//! Parent { tag3: vec![], tag12: Some(Tag12::Tag2(Tag2 {})) }
170//! );
171//! ```
172//!
173//! ### `#[xml(text)]`
174//!
175//! Specifies that a struct field is text content.
176//! Support `Cow<str>`, `Vec<Cow<str>>`, `Option<Cow<str>>`,
177//! `T`, `Vec<T>`, `Option<T>` where `T: FromStr + Display`.
178//!
179//! ```rust
180//! use std::borrow::Cow;
181//! use strong_xml::{XmlRead, XmlWrite};
182//!
183//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
184//! #[xml(tag = "parent")]
185//! struct Parent<'a> {
186//! #[xml(text)]
187//! content: Cow<'a, str>,
188//! }
189//!
190//! assert_eq!(
191//! (Parent { content: "content".into() }).to_string().unwrap(),
192//! r#"<parent>content</parent>"#
193//! );
194//!
195//! assert_eq!(
196//! Parent::from_str(r#"<parent></parent>"#).unwrap(),
197//! Parent { content: "".into() }
198//! );
199//! ```
200//!
201//! ### `#[xml(flatten_text = "")]`
202//!
203//! Specifies that a struct field is child text element.
204//! Support `Cow<str>`, `Vec<Cow<str>>`, `Option<Cow<str>>`,
205//! `T`, `Vec<T>`, `Option<T>` where `T: FromStr + Display`.
206//!
207//! ```rust
208//! use std::borrow::Cow;
209//! use strong_xml::{XmlRead, XmlWrite};
210//!
211//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
212//! #[xml(tag = "parent")]
213//! struct Parent<'a> {
214//! #[xml(flatten_text = "child")]
215//! content: Cow<'a, str>,
216//! }
217//!
218//! assert_eq!(
219//! (Parent { content: "content".into() }).to_string().unwrap(),
220//! r#"<parent><child>content</child></parent>"#
221//! );
222//!
223//! assert_eq!(
224//! Parent::from_str(r#"<parent><child></child></parent>"#).unwrap(),
225//! Parent { content: "".into() }
226//! );
227//! ```
228//!
229//! ### `#[xml(cdata)]`
230//!
231//! Specifies a CDATA text. Should be used together with `text` or `flatten_text`.
232//!
233//! > `#[xml(cdata)]` only changes the behavior of writing,
234//! > text field without `#[xml(cdata)]` can still works with cdata tag.
235//!
236//! ```rust
237//! use std::borrow::Cow;
238//! use strong_xml::{XmlRead, XmlWrite};
239//!
240//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
241//! #[xml(tag = "parent")]
242//! struct Parent<'a> {
243//! #[xml(text, cdata)]
244//! content: Cow<'a, str>,
245//! }
246//!
247//! assert_eq!(
248//! (Parent { content: "content".into() }).to_string().unwrap(),
249//! r#"<parent><![CDATA[content]]></parent>"#
250//! );
251//! ```
252//!
253//! ```rust
254//! use std::borrow::Cow;
255//! use strong_xml::{XmlRead, XmlWrite};
256//!
257//! #[derive(XmlWrite, XmlRead, PartialEq, Debug)]
258//! #[xml(tag = "parent")]
259//! struct Parent<'a> {
260//! #[xml(flatten_text = "code", cdata)]
261//! content: Cow<'a, str>,
262//! }
263//!
264//! assert_eq!(
265//! (Parent { content: r#"hello("deities!");"#.into() }).to_string().unwrap(),
266//! r#"<parent><code><![CDATA[hello("deities!");]]></code></parent>"#
267//! );
268//! ```
269//!
270//! ### `#[xml(default)]`
271//!
272//! Use `Default::default()` if the value is not present when reading.
273//!
274//! ```rust
275//! use std::borrow::Cow;
276//! use strong_xml::XmlRead;
277//!
278//! #[derive(XmlRead, PartialEq, Debug)]
279//! #[xml(tag = "root")]
280//! struct Root {
281//! #[xml(default, attr = "attr")]
282//! attr: bool,
283//! }
284//!
285//! assert_eq!(
286//! Root::from_str(r#"<root/>"#).unwrap(),
287//! Root { attr: false }
288//! );
289//!
290//! assert_eq!(
291//! Root::from_str(r#"<root attr="1"/>"#).unwrap(),
292//! Root { attr: true }
293//! );
294//! ```
295//!
296//! ## License
297//!
298//! MIT
299
300#[cfg(feature = "log")]
301mod log;
302#[cfg(not(feature = "log"))]
303mod noop_log;
304
305mod xml_error;
306mod xml_escape;
307mod xml_read;
308mod xml_reader;
309mod xml_unescape;
310mod xml_write;
311mod xml_writer;
312
313pub use self::xml_error::{XmlError, XmlResult};
314pub use self::xml_read::{XmlRead, XmlReadOwned};
315pub use self::xml_reader::XmlReader;
316pub use self::xml_write::XmlWrite;
317pub use self::xml_writer::XmlWriter;
318
319pub use strong_xml_derive::{XmlRead, XmlWrite};
320
321pub use xmlparser;
322
323pub mod utils {
324 pub use super::xml_escape::xml_escape;
325 pub use super::xml_unescape::xml_unescape;
326}