2016-06-22 88 views
9

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

事情是这样的:

<?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的新手,我很难搞清楚如何执行这个任务。

回答

14

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

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

添加包装箱到你Cargo.toml

我们可以手动执行反串行化代码,或者我们可以通过使用serde_derive箱子自动生成它。

[dependencies] 
serde_derive = "1.0" 
serde = "1.0" 
serde_xml_rs = "0.2.0" 

添加注释到您的结构

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

打开包含XML的字符串转换成对象

现在到了容易的部分。您在您的字符串上调用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); 
}