我正在try 编写一个程序,将XML文件读入之前定义的Rust struct .

比如:

<?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 ,我很难想出如何完成这项任务.

推荐答案

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

我将描述如何使用serde+serde_xml_rs将XML反序列化为Rust struct .

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需要了解你的 struct .为了帮助它,而不是为项目中的每个 struct 生成代码,您需要对所需的 struct 进行注释.Debug派生是为了方便我们用println!打印 struct ,以判断是否一切正常.Deserialize边界通知serde生成代码.如果希望将xml标记的内容视为文本,则需要将应该包含文本的字段"重命名"为$value.$value的命名在serde_xml_rs crate 的创建过程中非常随意,但不能与实际字段冲突,因为字段名称不能包含$个符号.

#[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);
}

Rust相关问答推荐

为什么复印是豆荚的一个重要特征?

什么是Rust惯用的方式来使特征向量具有单个向量项的别名?

Rust TcpStream不能在读取后写入,但可以在不读取的情况下写入.为什么?

如何计算迭代器适配器链中过滤的元素的数量

函数内模块的父作用域的访问类型

在使用AWS SDK for Rust时,如何使用硬编码访问密钥ID和密钥凭据?

为什么`AlternateScreen`在读取输入键时需要按Enter键?

如何设置activx websocket actorless的消息大小限制?

使用 Option 来分配?

可选包装枚举的反序列化

需要一个有序向量来进行 struct 初始化

当没有实际结果时,如何在 Rust 中强制执行错误处理?

为什么我们有两种方法来包含 serde_derive?

从 Rust 中的 if/else 中的引用创建 MappedRwLockWriteGuard

如何递归传递闭包作为参数?

如何从 x86_64 Mac 构建 M1 Mac?

n 个范围的笛卡尔积

将 `&T` 转换为新类型 `&N`

SDL2 没有在终端键上触发?

如果我不想运行析构函数,如何移出具有析构函数的 struct ?