将XML文件读入struct

时间:2016-06-22 14:01:24

标签: xml xml-parsing rust

我正在尝试编写一个将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的新手,我很难搞清楚如何执行这项任务。

1 个答案:

答案 0 :(得分:22)

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

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

将包装箱添加到Cargo.toml

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

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

在结构中添加注释

Serde需要了解你的结构。为了帮助它而不为项目中的每个结构生成代码,您需要注释所需的结构。 Debug推导是我们可以使用println!轻松打印结构以检查是否一切正常。 Deserialize绑定是通知serde生成代码的内容。如果要将xml标记的内容视为文本,则需要重命名&#34;应包含$value文本的字段。 $value的命名在创建serde_xml_rs包中时非常随意,但永远不会与实际字段发生冲突,因为字段名称不能包含$个符号。< / p>

#[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,
}

将包含xml的String转换为对象

现在很简单。您在字符串上调用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);
}