diff --git a/src/de/mod.rs b/src/de/mod.rs index 743ba04b..1963f8c3 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -12,13 +12,27 @@ //! //! //! +//! Table of Contents +//! ================= +//! - [Mapping XML to Rust types](#mapping-xml-to-rust-types) +//! - [Optional attributes and elements](#optional-attributes-and-elements) +//! - [Choices (`xs:choice` XML Schema type)](#choices-xschoice-xml-schema-type) +//! - [Sequences (`xs:all` and `xs:sequence` XML Schema types)](#sequences-xsall-and-xssequence-xml-schema-types) +//! - [Composition Rules](#composition-rules) +//! - [Difference between `$text` and `$value` special names](#difference-between-text-and-value-special-names) +//! - [`$text`](#text) +//! - [`$value`](#value) +//! - [Primitives and sequences of primitives](#primitives-and-sequences-of-primitives) +//! - [Structs and sequences of structs](#structs-and-sequences-of-structs) +//! - [Enums and sequences of enums](#enums-and-sequences-of-enums) +//! - [Frequently Used Patterns](#frequently-used-patterns) +//! - [`` lists](#element-lists) +//! +//! +//! //! Mapping XML to Rust types //! ========================= //! -//! - [Optional attributes and elements](#optional-attributes-and-elements) -//! - [Choices (`xs:choice` XML Schema type)](#choices-xschoice-xml-schema-type) -//! - [Sequences (`xs:all` and `xs:sequence` XML Schema types)](#sequences-xsall-and-xssequence-xml-schema-types) -//! //! Type names are never considered when deserializing, so you could name your //! types as you wish. Other general rules: //! - `struct` field name could be represented in XML only as an attribute name @@ -852,6 +866,8 @@ //! //! This bug is tracked in [#510] //! +//! +//! See also [Frequently Used Patterns](#element-lists). //! //! //! @@ -1301,7 +1317,8 @@ //! //! //! -//! # Difference between `$text` and `$value` special names +//! Difference between `$text` and `$value` special names +//! ===================================================== //! //! quick-xml supports two special names for fields -- `$text` and `$value`. //! Although they may seem the same, there is a distinction. Two different @@ -1527,9 +1544,109 @@ //! that is not enforced, so you can theoretically have both, but you should //! avoid that. //! +//! +//! +//! Frequently Used Patterns +//! ======================== +//! +//! Some XML constructs used as frequent, that it is worth to document recommended +//! way to represent them in the Rust. The sections below describes them. +//! +//! ## `` lists +//! Many XML formats wrap lists of elements in the additional container, +//! although this is not required by the XML rules: +//! +//! ```xml +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! +//! ``` +//! In this case, there is a great desire to describe this XML in this way: +//! ``` +//! /// Represents +//! type Element = (); +//! +//! /// Represents ... +//! struct AnyName { +//! // Incorrect +//! list: Vec, +//! } +//! ``` +//! This will not work, because potentially `` element can have attributes +//! and other elements inside. You should define the struct for the `` +//! explicitly, as you do that in the XSD for that XML: +//! ``` +//! /// Represents +//! type Element = (); +//! +//! /// Represents ... +//! struct AnyName { +//! // Correct +//! list: List, +//! } +//! struct List { +//! element: Vec, +//! } +//! ``` +//! +//! If you want to simplify your API, you could write a simple function for unwrapping +//! inner list and apply it via [`deserialize_with`]: +//! +//! ``` +//! # use pretty_assertions::assert_eq; +//! use quick_xml::de::from_str; +//! use serde::{Deserialize, Deserializer}; +//! +//! /// Represents +//! type Element = (); +//! +//! /// Represents ... +//! #[derive(Deserialize, Debug, PartialEq)] +//! struct AnyName { +//! #[serde(deserialize_with = "unwrap_list")] +//! list: Vec, +//! } +//! +//! fn unwrap_list<'de, D>(deserializer: D) -> Result, D::Error> +//! where +//! D: Deserializer<'de>, +//! { +//! #[derive(Deserialize)] +//! struct List { +//! // default allows empty list +//! #[serde(default)] +//! element: Vec, +//! } +//! Ok(List::deserialize(deserializer)?.element) +//! } +//! +//! assert_eq!( +//! AnyName { list: vec![(), (), ()] }, +//! from_str(" +//! +//! +//! +//! +//! +//! +//! +//! ").unwrap(), +//! ); +//! ``` +//! +//! Instead of writing such functions manually, you also could try . +//! //! [buggy]: https://github.com/serde-rs/serde/issues/1183 //! [do not support]: https://github.com/serde-rs/serde/issues/1905 //! [specification]: https://www.w3.org/TR/xmlschema11-1/#Simple_Type_Definition +//! [`deserialize_with`]: https://serde.rs/field-attrs.html#deserialize_with //! [#474]: https://github.com/tafia/quick-xml/issues/474 //! [#510]: https://github.com/tafia/quick-xml/issues/510