#xml-parser #xml #derive #proc-macro

hard-xml

基于xmlparser的强类型XML。

18个稳定版本

1.36.0 2024年3月13日
1.27.0 2023年9月1日
1.25.0 2023年5月26日
1.21.0 2022年12月17日
0.6.3 2022年7月5日

#220 in 解析器实现

Download history 622/week @ 2024-04-23 918/week @ 2024-04-30 488/week @ 2024-05-07 419/week @ 2024-05-14 662/week @ 2024-05-21 499/week @ 2024-05-28 660/week @ 2024-06-04 712/week @ 2024-06-11 545/week @ 2024-06-18 1282/week @ 2024-06-25 1323/week @ 2024-07-02 907/week @ 2024-07-09 1178/week @ 2024-07-16 869/week @ 2024-07-23 1666/week @ 2024-07-30 1302/week @ 2024-08-06

5,100 每月下载量
用于 19 个crates (5 个直接)

MIT 许可证

52KB
946 代码行

hard-xml

基于xmlparser的强类型XML。

这是对 https://github.com/PoiScript/strong-xml 的分支,因为它已经不再维护。

Crates.io Document

快速开始

cargo add hard-xml
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<Cow<'a, str>>,
    #[xml(child = "child")]
    child: Vec<Child<'a>>,
}

#[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#"<parent attr1="val"/>"#
);

assert_eq!(
    Parent::from_str(r#"<parent attr1="val" attr2="val"><child></child></parent>"#).unwrap(),
    Parent { attr1: "val".into(), attr2: Some("val".into()), child: vec![Child { text: "".into() }] }
);

属性

#[xml(tag= "")]

指定结构体或枚举变体的XML标签。

#[derive(XmlWrite, XmlRead, PartialEq, Debug)]
#[xml(tag = "parent")]
struct Parent {}

assert_eq!(
    (Parent {}).to_string().unwrap(),
    r#"<parent/>"#
);

assert_eq!(
    Parent::from_str(r#"<parent/>"#).unwrap(),
    Parent {}
);
#[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#"<tag1/>"#
);

assert_eq!(
    Tag::from_str(r#"<tag2></tag2>"#).unwrap(),
    Tag::Tag2(Tag2 {})
);

#[xml(attr= "")]

指定结构体字段是属性。支持 Cow<str>Option<Cow<str>>TOption<T> 其中 T: FromStr + Display

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#"<parent attr="42"/>"#
);

assert_eq!(
    Parent::from_str(r#"<parent attr="48"></parent>"#).unwrap(),
    Parent { attr: 48 }
);

#[xml(child= "")]

指定结构体字段是一个子元素。支持 TOption<T>Vec<T> 其中 T: XmlRead + XmlWrite

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<Tag3>,
    #[xml(child = "tag1", child = "tag2")]
    tag12: Option<Tag12>
}

assert_eq!(
    (Parent { tag3: vec![Tag3 {}], tag12: None }).to_string().unwrap(),
    r#"<parent><tag3/></parent>"#
);

assert_eq!(
    Parent::from_str(r#"<parent><tag2></tag2></parent>"#).unwrap(),
    Parent { tag3: vec![], tag12: Some(Tag12::Tag2(Tag2 {})) }
);

#[xml(text)]

指定结构体字段是文本内容。支持 Cow<str>Vec<Cow<str>>Option<Cow<str>>TVec<T>Option<T> 其中 T: FromStr + Display

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#"<parent>content</parent>"#
);

assert_eq!(
    Parent::from_str(r#"<parent></parent>"#).unwrap(),
    Parent { content: "".into() }
);

#[xml(flatten_text= "")]

指定结构体字段为子文本元素。支持 Cow<str>Vec<Cow<str>>Option<Cow<str>>TVec<T>Option<T>,其中 T: FromStr + Display

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#"<parent><child>content</child></parent>"#
);

assert_eq!(
    Parent::from_str(r#"<parent><child></child></parent>"#).unwrap(),
    Parent { content: "".into() }
);

#[xml(cdata)]

指定一个 CDATA 文本。应与 textflatten_text 一起使用。

#[xml(cdata)] 仅更改写入行为,不带 #[xml(cdata)] 的文本字段仍然可以使用 cdata 标签。

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#"<parent><![CDATA[content]]></parent>"#
);
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#"<parent><code><![CDATA[hello("deities!");]]></code></parent>"#
);

#[xml(默认)]

在读取时如果值不存在,请使用 Default::default()

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#"<root/>"#).unwrap(),
    Root { attr: false }
);

assert_eq!(
    Root::from_str(r#"<root attr="1"/>"#).unwrap(),
    Root { attr: true }
);

许可证

MIT

许可证:MIT

依赖项

~2MB
~45K SLoC