12 个版本

0.6.0 2022 年 8 月 31 日
0.5.1 2021 年 9 月 21 日
0.5.0 2021 年 8 月 10 日
0.4.1 2021 年 1 月 10 日
0.1.2 2017 年 3 月 20 日

编码 类别中排名 25

Download history 62137/week @ 2024-03-14 60166/week @ 2024-03-21 55355/week @ 2024-03-28 63347/week @ 2024-04-04 66173/week @ 2024-04-11 68567/week @ 2024-04-18 68168/week @ 2024-04-25 73253/week @ 2024-05-02 66715/week @ 2024-05-09 90793/week @ 2024-05-16 85322/week @ 2024-05-23 94448/week @ 2024-05-30 93770/week @ 2024-06-06 96494/week @ 2024-06-13 93789/week @ 2024-06-20 72486/week @ 2024-06-27

每月下载量 375,658
613 crate 使用(279 个直接使用)

MIT 许可证

65KB
1.5K SLoC

serde-xml-rs

Build Status

xml-rs 基于 Serde 的解码器(兼容 1.0)

示例用法

use serde::{Deserialize, Serialize};
use serde_xml_rs::{from_str, to_string};

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Item {
    name: String,
    source: String,
}

fn main() {
    let src = r#"<Item><name>Banana</name><source>Store</source></Item>"#;
    let should_be = Item {
        name: "Banana".to_string(),
        source: "Store".to_string(),
    };

    let item: Item = from_str(src).unwrap();
    assert_eq!(item, should_be);

    let reserialized_item = to_string(&item).unwrap();
    assert_eq!(src, reserialized_item);
}

lib.rs:

Serde XML

XML 是一种灵活的标记语言,仍然用于应用程序之间的数据共享或用于编写配置文件。

Serde XML 提供了一种将文本和强类型 Rust 数据结构之间进行转换的方法。

注意事项

Serde 框架主要是针对像 JSON 或 YAML 这样的格式设计的。与 XML 相比,这些格式具有更严格的语法优势,这使得在没有伴随模式的情况下知道字段的类型成为可能,并禁止在同一对象中多次重复相同的标签。

例如,将以下文档编码为 YAML 并不简单。

<document>
  <header>A header</header>
  <section>First section</section>
  <section>Second section</section>
  <sidenote>A sidenote</sidenote>
  <section>Third section</section>
  <sidenote>Another sidenote</sidenote>
  <section>Fourth section</section>
  <footer>The footer</footer>
</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

其他显著差异

  • XML 需要一个命名根节点。
  • XML 有一个命名空间系统。
  • XML 区分属性、子标签和内容。
  • 在 XML 中,节点的顺序有时很重要。

基本示例

use serde::{Deserialize, Serialize};
use serde_xml_rs::{from_str, to_string};

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Item {
    name: String,
    source: String,
}

fn main() {
    let src = r#"<?xml version="1.0" encoding="UTF-8"?><Item><name>Banana</name><source>Store</source></Item>"#;
    let should_be = Item {
        name: "Banana".to_string(),
        source: "Store".to_string(),
    };

    let item: Item = from_str(src).unwrap();
    assert_eq!(item, should_be);

    let reserialized_item = to_string(&item).unwrap();
    assert_eq!(src, reserialized_item);
}

标签内容


#[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#"<document><content>Lorem ipsum</content></document>"#;
    let document: Document = from_str(src).unwrap();
    assert_eq!(document.content.value, "Lorem ipsum");
}

重复标签


#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct PlateAppearance {
    #[serde(rename = "$value")]
    events: Vec<Event>
}

#[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<Base>, 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#"
        <plate-appearance>
          <pitch speed="95" type="FourSeam" outcome="Ball" />
          <pitch speed="91" type="FourSeam" outcome="Strike" />
          <pitch speed="85" type="Changeup" outcome="Ball" />
          <runner from="First" to="Second" outcome="Steal" />
          <pitch speed="89" type="Slider" outcome="Strike" />
          <pitch speed="88" type="Curve" outcome="Hit" />
        </plate-appearance>"#;
    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 }));
}

自定义 EventReader

use serde::{Deserialize, Serialize};
use serde_xml_rs::{from_str, to_string, de::Deserializer};
use xml::reader::{EventReader, ParserConfig};

#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Item {
    name: String,
    source: String,
}

fn main() {
    let src = r#"<Item><name>  Banana  </name><source>Store</source></Item>"#;
    let should_be = Item {
        name: "  Banana  ".to_string(),
        source: "Store".to_string(),
    };

    let config = ParserConfig::new()
        .trim_whitespace(false)
        .whitespace_to_characters(true);
    let event_reader = EventReader::new_with_config(src.as_bytes(), config);
    let item = Item::deserialize(&mut Deserializer::new(event_reader)).unwrap();
    assert_eq!(item, should_be);
}

依赖关系

~0.7–1.3MB
~30K SLoC