diff --git a/README.md b/README.md index f2e530c..ba23d1e 100644 --- a/README.md +++ b/README.md @@ -2,61 +2,32 @@ [![Build Status](https://travis-ci.org/RReverser/serde-xml-rs.svg?branch=master)](https://travis-ci.org/RReverser/serde-xml-rs) -xml-rs based deserializer for Serde (compatible with 0.9+) +`xml-rs` based deserializer for Serde (compatible with 1.0) -## Usage - -Use `serde_xml_rs::from_reader(...)` on any type that implements [`std::io::Read`](https://doc.rust-lang.org/std/io/trait.Read.html) as following: +## Example usage ```rust -#[macro_use] -extern crate serde_derive; -extern crate serde; -extern crate serde_xml_rs; - -use serde_xml_rs::from_reader; +use serde; +use serde_derive::{Deserialize, Serialize}; +use serde_xml_rs::{from_str, to_string}; -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize, PartialEq)] struct Item { - pub name: String, - pub source: String -} - -#[derive(Debug, Deserialize)] -struct Project { - pub name: String, - - #[serde(rename = "Item", default)] - pub items: Vec + name: String, + source: String, } fn main() { - let s = r##" - - - - "##; - let project: Project = from_reader(s.as_bytes()).unwrap(); - println!("{:#?}", project); -} -``` - -Alternatively, you can use `serde_xml_rs::Deserializer` to create a deserializer from a preconfigured [`xml_rs::EventReader`](https://netvl.github.io/xml-rs/xml/reader/struct.EventReader.html). - -## Parsing the "value" of a tag + let src = r#"BananaStore"#; + let should_be = Item { + name: "Banana".to_string(), + source: "Store".to_string(), + }; -If you have an input of the form `bar`, and you want to get at the`bar`, you can use the special name `$value`: + let item: Item = from_str(src).unwrap(); + assert_eq!(item, should_be); -```rust,ignore -struct Foo { - pub abc: String, - #[serde(rename = "$value")] - pub body: String, + let reserialized_item = to_string(&item).unwrap(); + assert_eq!(src, reserialized_item); } ``` - -## Parsed representations - -Deserializer tries to be as intuitive as possible. - -However, there are some edge cases where you might get unexpected errors, so it's best to check out [`tests`](tests/test.rs) for expectations. diff --git a/src/lib.rs b/src/lib.rs index c5a8144..ab10690 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,56 @@ +//! # Serde XML //! +//! XML is a flexible markup language that is still used for sharing data between applications or +//! for writing configuration files. //! -//! # Examples +//! Serde XML provides a way to convert between text and strongly-typed Rust data structures. //! -//! ```rust -//! extern crate serde; -//! extern crate serde_xml_rs; +//! ## 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. //! -//! #[macro_use] -//! extern crate serde_derive; +//! For example, encoding the following document in YAML is not trivial. +//! +//! ```xml +//! +//!
A header
+//!
First section
+//!
Second section
+//! A sidenote +//!
Third section
+//! Another sidenote +//!
Fourth section
+//!
The footer
+//!
+//! ``` +//! +//! 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)] @@ -31,6 +73,89 @@ //! 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#"Lorem ipsum"#; +//! 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 +//! } +//! +//! #[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, 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#" +//! +//! +//! +//! +//! +//! +//! +//! "#; +//! 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 })); +//! } +//! ``` pub mod de; mod error; diff --git a/tests/readme.rs b/tests/readme.rs deleted file mode 100644 index 51ec7d7..0000000 --- a/tests/readme.rs +++ /dev/null @@ -1,6 +0,0 @@ -use docmatic; - -#[test] -fn test_readme() { - docmatic::assert_file("README.md"); -}