将 XML 文件读入结构 [英] Read XML file into struct
问题描述
我正在尝试编写一个将 XML 文件读入之前定义的 Rust 结构的程序.
I am trying to write a program that reads an XML file into a previously defined 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 新手,我很难弄清楚如何执行这项任务.
I looked at xml-rs because it currently appears to be the most popular XML library. Being new to Rust, I have a hard time figuring out how to perform this task.
推荐答案
Rust 对自动生成(反)序列化代码有很好的支持.遗留的 rustc-serialize
需要很少的设置.然后是 serde
crate,它是一个全新的(反)序列化框架,允许多种格式和详细的自定义配置,但需要更多的初始设置.
Rust has great support for automatically generating (de)serialization code. There's the legacy rustc-serialize
which requires very little setup. Then there's the serde
crate which is a completely new (de)serialization framework that allows many formats and detailed custom configurations, but requires a little more initial setup.
我将介绍如何使用 serde
+ serde_xml_rs
将 XML 反序列化为 Rust 结构.
I'm going to describe how to use serde
+ serde_xml_rs
to deserialize the XML to the Rust-structs.
我们可以手动实现反序列化代码,也可以使用 serde_derive
crate 自动生成它.
We could either implement the deserialization code manually, or we can generate it automatically by using the serde_derive
crate.
[dependencies]
serde_derive = "1.0"
serde = "1.0"
serde-xml-rs = "0.3.1"
为您的结构添加注释
Serde 需要了解您的结构.为了帮助它而不是为项目中的每个结构生成代码,您需要注释所需的结构.Debug
派生是为了让我们可以轻松地使用 println!
打印结构,以检查一切是否正常.Deserialize
绑定通知 serde
生成代码.如果要将 xml 标记的内容视为文本,则需要重命名";应包含 $value
文本的字段.$value
的命名在 serde_xml_rs
crate 的创建中是非常随意的,但不能与实际的字段发生冲突,因为字段名不能包含 $
符号.
Add annotations to your structs
Serde needs to know about your structs. To aid it and not generate code for every single struct in your project, you need to annotate the structs you want. The Debug
derivation is so we can easily print the structs with println!
to inspect whether everything worked. The Deserialize
bound is what notifies serde
to generate code. If you want to treat the contents of an xml tag as text, you need to "rename" the field that should contain the text to $value
. The naming of $value
was done very arbitrarily in the creation of the serde_xml_rs
crate, but can never collide with an actual field, because field names can't contain $
signs.
#[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);
}
这篇关于将 XML 文件读入结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!