# hard-xml Strong typed xml, based on xmlparser. This is a fork of https://github.com/PoiScript/strong-xml as it has become unmaintained. [![Crates.io](https://img.shields.io/crates/v/hard-xml.svg)](https://crates.io/crates/hard-xml) [![Document](https://docs.rs/hard-xml/badge.svg)](https://docs.rs/hard-xml) ### Quick Start ```sh cargo add hard-xml ``` ```rust use std::borrow::Cow; use hard_xml::{XmlRead, XmlWrite}; #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "parent")] struct Parent<'a> { #[xml(attr = "attr1")] attr1: Cow<'a, str>, #[xml(attr = "attr2")] attr2: Option>, #[xml(child = "child")] child: Vec>, } #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "child")] struct Child<'a> { #[xml(text)] text: Cow<'a, str>, } assert_eq!( (Parent { attr1: "val".into(), attr2: None, child: vec![] }).to_string().unwrap(), r#""# ); assert_eq!( Parent::from_str(r#""#).unwrap(), Parent { attr1: "val".into(), attr2: Some("val".into()), child: vec![Child { text: "".into() }] } ); ``` ### Attributes #### `#[xml(tag = "")]` Specifies the xml tag of a struct or an enum variant. ```rust #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "parent")] struct Parent {} assert_eq!( (Parent {}).to_string().unwrap(), r#""# ); assert_eq!( Parent::from_str(r#""#).unwrap(), Parent {} ); ``` ```rust #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "tag1")] struct Tag1 {} #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "tag2")] struct Tag2 {} #[derive(XmlWrite, XmlRead, PartialEq, Debug)] enum Tag { #[xml(tag = "tag1")] Tag1(Tag1), #[xml(tag = "tag2")] Tag2(Tag2), } assert_eq!( (Tag::Tag1(Tag1 {})).to_string().unwrap(), r#""# ); assert_eq!( Tag::from_str(r#""#).unwrap(), Tag::Tag2(Tag2 {}) ); ``` #### `#[xml(attr = "")]` Specifies that a struct field is attribute. Support `Cow`, `Option>`, `T` and `Option` where `T: FromStr + Display`. ```rust use hard_xml::{XmlRead, XmlWrite}; #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "parent")] struct Parent { #[xml(attr = "attr")] attr: usize } assert_eq!( (Parent { attr: 42 }).to_string().unwrap(), r#""# ); assert_eq!( Parent::from_str(r#""#).unwrap(), Parent { attr: 48 } ); ``` #### `#[xml(child = "")]` Specifies that a struct field is a child element. Support `T`, `Option`, `Vec` where `T: XmlRead + XmlWrite`. ```rust use hard_xml::{XmlRead, XmlWrite}; #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "tag1")] struct Tag1 {} #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "tag2")] struct Tag2 {} #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "tag3")] struct Tag3 {} #[derive(XmlWrite, XmlRead, PartialEq, Debug)] enum Tag12 { #[xml(tag = "tag1")] Tag1(Tag1), #[xml(tag = "tag2")] Tag2(Tag2), } #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "parent")] struct Parent { #[xml(child = "tag3")] tag3: Vec, #[xml(child = "tag1", child = "tag2")] tag12: Option } assert_eq!( (Parent { tag3: vec![Tag3 {}], tag12: None }).to_string().unwrap(), r#""# ); assert_eq!( Parent::from_str(r#""#).unwrap(), Parent { tag3: vec![], tag12: Some(Tag12::Tag2(Tag2 {})) } ); ``` #### `#[xml(text)]` Specifies that a struct field is text content. Support `Cow`, `Vec>`, `Option>`, `T`, `Vec`, `Option` where `T: FromStr + Display`. ```rust use std::borrow::Cow; use hard_xml::{XmlRead, XmlWrite}; #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "parent")] struct Parent<'a> { #[xml(text)] content: Cow<'a, str>, } assert_eq!( (Parent { content: "content".into() }).to_string().unwrap(), r#"content"# ); assert_eq!( Parent::from_str(r#""#).unwrap(), Parent { content: "".into() } ); ``` #### `#[xml(flatten_text = "")]` Specifies that a struct field is child text element. Support `Cow`, `Vec>`, `Option>`, `T`, `Vec`, `Option` where `T: FromStr + Display`. ```rust use std::borrow::Cow; use hard_xml::{XmlRead, XmlWrite}; #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "parent")] struct Parent<'a> { #[xml(flatten_text = "child")] content: Cow<'a, str>, } assert_eq!( (Parent { content: "content".into() }).to_string().unwrap(), r#"content"# ); assert_eq!( Parent::from_str(r#""#).unwrap(), Parent { content: "".into() } ); ``` #### `#[xml(cdata)]` Specifies a CDATA text. Should be used together with `text` or `flatten_text`. > `#[xml(cdata)]` only changes the behavior of writing, > text field without `#[xml(cdata)]` can still works with cdata tag. ```rust use std::borrow::Cow; use hard_xml::{XmlRead, XmlWrite}; #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "parent")] struct Parent<'a> { #[xml(text, cdata)] content: Cow<'a, str>, } assert_eq!( (Parent { content: "content".into() }).to_string().unwrap(), r#""# ); ``` ```rust use std::borrow::Cow; use hard_xml::{XmlRead, XmlWrite}; #[derive(XmlWrite, XmlRead, PartialEq, Debug)] #[xml(tag = "parent")] struct Parent<'a> { #[xml(flatten_text = "code", cdata)] content: Cow<'a, str>, } assert_eq!( (Parent { content: r#"hello("deities!");"#.into() }).to_string().unwrap(), r#""# ); ``` #### `#[xml(default)]` Use `Default::default()` if the value is not present when reading. ```rust use std::borrow::Cow; use hard_xml::XmlRead; #[derive(XmlRead, PartialEq, Debug)] #[xml(tag = "root")] struct Root { #[xml(default, attr = "attr")] attr: bool, } assert_eq!( Root::from_str(r#""#).unwrap(), Root { attr: false } ); assert_eq!( Root::from_str(r#""#).unwrap(), Root { attr: true } ); ``` ### License MIT License: MIT