2016-06-22 12 views
9

Ich versuche, ein Programm zu schreiben, das eine XML-Datei in eine zuvor definierte Rust-Struktur liest.XML-Datei in Struktur lesen

Etwas wie folgt aus:

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

In diese:

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

ich xml-rs sah, weil es derzeit die beliebteste XML-Bibliothek zu sein scheint. Da ich neu in Rust bin, fällt es mir schwer herauszufinden, wie ich diese Aufgabe erfüllen soll.

Antwort

14

Rust bietet eine hervorragende Unterstützung für die automatische Generierung von (De) Serialisierungscode. Es gibt das Vermächtnis rustc-serialize, das sehr wenig Setup erfordert. Dann gibt es die serde Kiste, die ein völlig neues (de) Serialisierungsframework ist, das viele Formate und detaillierte benutzerdefinierte Konfigurationen erlaubt, aber ein wenig mehr anfängliche Einrichtung erfordert.

Ich werde beschreiben, wie serde + zu Deserialisierung der XML zu den Rust-Strukturen zu verwenden.

Fügen Sie die Kisten, um Ihre Cargo.toml

Wir entweder manuell den Deserialisierung Code implementieren könnte, oder wir können es automatisch unter Verwendung der serde_derive Kiste erzeugen.

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

Hinzufügen von Anmerkungen zu Ihrem structs

Serde über Ihre structs wissen muss. Um dies zu unterstützen und keinen Code für jede einzelne Struktur in Ihrem Projekt zu generieren, müssen Sie die gewünschten Strukturen mit Anmerkungen versehen. Die Debug Ableitung ist so, dass wir die Strukturen einfach mit println! drucken können, um zu überprüfen, ob alles funktioniert. Die Deserialize Grenze ist, was serde benachrichtigt, um Code zu generieren. Wenn Sie den Inhalt eines XML-Tags als Text behandeln möchten, müssen Sie das Feld, das den Text enthalten soll, in "$value" umbenennen. Die Benennung $value wurde sehr willkürlich bei der Erstellung der serde_xml_rs Kiste vorgenommen, kann aber niemals mit einem tatsächlichen Feld kollidieren, da Feldnamen keine $ Zeichen enthalten dürfen.

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

einen String drehen xml in ein Objekt

Jetzt kommt der einfache Teil enthält. Sie rufen serde_xml::from_str auf Zeichenfolge und verwenden Sie einen Fehler oder einen Wert vom Typ Node erhalten:

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