2016-06-22 41 views
9

Sto provando a scrivere un programma che legge un file XML in una struttura di ruggine precedentemente definita.Legge il file XML nella struct

Qualcosa di simile a questo:

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

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

ho guardato xml-rs perché attualmente sembra essere la libreria XML più popolari. Essendo nuovo di Rust, ho difficoltà a capire come eseguire questo compito.

risposta

14

Rust ha un ottimo supporto per la generazione automatica del codice di (de) serializzazione. C'è l'eredità rustc-serialize che richiede pochissima installazione. Poi c'è la cassa serde che è una struttura completamente nuova (de) serializzazione che consente molti formati e configurazioni personalizzate dettagliate, ma richiede un po 'più di configurazione iniziale.

Descriverò come utilizzare serde + serde_xml_rs per deserializzare l'XML nelle strutture di Rust.

Aggiungi le casse per il vostro Cargo.toml

potevamo o implementare il codice deserializzazione manualmente, o siamo in grado di generare automaticamente utilizzando il serde_derive cassa.

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

Aggiungi annotazioni ai tuoi struct

Serde ha bisogno di conoscere le vostre strutture. Per aiutarlo e non generare codice per ogni singola struttura nel progetto, è necessario annotare le strutture che si desidera. La derivazione Debug è così che possiamo facilmente stampare le strutture con println! per verificare se tutto ha funzionato. Il limite Deserialize è quello che notifica serde per generare il codice. Se si desidera trattare il contenuto di un tag xml come testo, è necessario "rinominare" il campo che dovrebbe contenere il testo a $value. La denominazione di $value è stata eseguita in modo molto arbitrario durante la creazione della cassa serde_xml_rs, ma non può mai scontrarsi con un campo effettivo, poiché i nomi dei campi non possono contenere i segni $.

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

trasformare una stringa contenente XML in un oggetto

Ora arriva la parte più facile. Si chiama serde_xml::from_str sulla stringa e si ottiene un errore o un valore di tipo 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); 
}