2016-06-22 25 views
9

Tôi đang cố gắng viết một chương trình đọc một tệp XML vào một cấu trúc Rust đã được định nghĩa trước đó.Đọc tệp XML thành cấu trúc

Something như thế này:

<?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> 

Into này:

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

Tôi nhìn xml-rs vì nó hiện dường như là thư viện XML phổ biến nhất. Là người mới đối với Rust, tôi có một thời gian khó khăn để tìm ra cách thực hiện nhiệm vụ này.

Trả lời

14

Rust có hỗ trợ tuyệt vời để tự động tạo (de) mã tuần tự hóa. Có di sản rustc-serialize yêu cầu thiết lập rất ít. Sau đó, có thùng serde là một khung công tác tuần tự hoàn toàn mới (de) cho phép nhiều định dạng và cấu hình tùy chỉnh chi tiết, nhưng yêu cầu thiết lập ban đầu hơn một chút.

Tôi sẽ mô tả cách sử dụng serde + serde_xml_rs để deserialize XML thành cấu trúc Rust.

Thêm thùng để bạn Cargo.toml

Chúng tôi có thể thực hiện một trong hai mã deserialization bằng tay, hoặc chúng ta có thể tạo ra nó tự động bằng cách sử dụng các serde_derive thùng.

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

Thêm chú thích để struct của bạn

Serde cần biết về cấu trúc của bạn. Để hỗ trợ nó và không tạo mã cho mỗi cấu trúc đơn lẻ trong dự án của bạn, bạn cần chú thích các cấu trúc mà bạn muốn. Các dẫn xuất Debug là vì vậy chúng tôi có thể dễ dàng in các cấu trúc với println! để kiểm tra xem mọi thứ có hoạt động hay không. Các ràng buộc Deserialize là những gì thông báo serde để tạo mã. Nếu bạn muốn xử lý nội dung của thẻ xml dưới dạng văn bản, bạn cần phải "đổi tên" trường sẽ chứa văn bản thành $value. Việc đặt tên của $value được thực hiện rất tùy ý trong việc tạo ra các thùng serde_xml_rs, nhưng không bao giờ có thể va chạm với một trường thực tế, bởi vì tên trường không thể chứa các dấu hiệu $.

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

Rẽ một String chứa xml thành một đối tượng

Bây giờ đến phần dễ dàng. Bạn gọi số serde_xml::from_str trên chuỗi của mình và bạn nhận được lỗi hoặc giá trị loại 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); 
} 
Các vấn đề liên quan