将XML文件读入struct

问题描述 投票:11回答:1

我正在尝试编写一个程序,将XML文件读入先前定义的Rust结构中。

像这样的东西:

<?xml version="1.0" encoding="UTF-8"?>
<note name="title">
  <body name="main_body">
    <layer content_type="something" count="99">
      <data id="13">
        Datacontent
      </data>
    </layer>
  </body>
</note>

进入:

struct Note {
    name: String,
    Body: Body 
}

struct Body {
    name: String,
    layers: Vec<Layer>,
}

struct Layer {
    content_type: String,
    count: u8,
    data: Vec<Data>,
}

struct Data {
    id: u8,
    // Datacontent?
}

我查看了xml-rs,因为它目前似乎是最流行的XML库。作为Rust的新手,我很难搞清楚如何执行这项任务。

xml xml-parsing rust
1个回答
23
投票

Rust非常支持自动生成(de)序列化代码。传统的rustc-serialize需要很少的设置。然后是serde crate,这是一个全新的(de)序列化框架,允许许多格式和详细的自定义配置,但需要更多的初始设置。

我将描述如何使用serde + serde_xml_rs将XML反序列化为Rust-structs。

Add the crates to your Cargo.toml

我们可以手动实现反序列化代码,也可以使用serde_derive crate自动生成它。

[dependencies]
serde_derive = "1.0"
serde = "1.0"
serde-xml-rs = "0.3.1"

Add annotations to your structs

Serde需要了解你的结构。为了帮助它而不为项目中的每个结构生成代码,您需要注释所需的结构。 Debug派生是这样的,我们可以用println!轻松打印结构,以检查是否一切正常。 Deserialize界限是通知serde生成代码。如果要将xml标记的内容视为文本,则需要将应包含文本的字段“重命名”为$value$value的命名在serde_xml_rs箱子的创建中非常随意地完成,但是永远不会与实际场地碰撞,因为场名不能包含$标志。

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_xml_rs;

#[derive(Deserialize, Debug)]
struct Note {
    name: String,
    body: Body,
}

#[derive(Deserialize, Debug)]
struct Body {
    name: String,
    #[serde(rename="layer")]
    layers: Vec<Layer>,
}

#[derive(Deserialize, Debug)]
struct Layer {
    content_type: String,
    count: u8,
    data: Vec<Data>,
}

#[derive(Deserialize, Debug)]
struct Data {
    id: u8,
    #[serde(rename="$value")]
    content: String,
}

Turn a String containing xml into an object

现在来了一个简单的部分。你在你的字符串上调用serde_xml::from_str,你得到一个错误或类型为Node的值:

fn main() {
    let note: Note = serde_xml_rs::deserialize(r##"
<?xml version="1.0" encoding="UTF-8"?>
<note name="title">
  <body name="main_body">
    <layer content_type="something" count="99">
      <data id="13">
        Datacontent
      </data>
    </layer>
  </body>
</note>
    "##.as_bytes()).unwrap();
    println!("{:#?}", note);
}
© www.soinside.com 2019 - 2024. All rights reserved.