CNier
March 24, 2023, 9:31am
1
Hi,
i'm parsing a new file xml as follows :
<GC version="x.x.x" endianness="little" db_path="xxx/yyy/zzz">
<Sys>
<Area>
<name>AAA</name>
<module>BBB</module>
</Area>
</Sys>
<Sys>
<Area>
<name>AAA</name>
<module>BBB</module>
</Area>
</Sys>
</GC>
and i suppose that this is the correct structure:
#[derive(Debug, Deserialize)]
pub struct GC{
version : i32,
endianness : String,
db_path : String,
GC: Vec<Sys>,
}
#[derive(Debug, Deserialize)]
struct Sys{
sys: Vec<Area>,
}
#[derive(Debug, Deserialize)]
struct Area {
Area: Vec<Group>,
}
#[derive(Debug, Deserialize)]
struct Group {
//#[serde(rename = "v")]
name: Vec<Name>,
module: Vec<Module>,
}
#[derive(Debug, Deserialize)]
struct Name{
//name: String,
#[serde(rename = "$value")]
value: String,
}
#[derive(Debug, Deserialize)]
struct Module{
//name: String,
#[serde(rename = "$value")]
value: String,
}
but it isn't . i don't know where i'm going wrong
jofas
March 24, 2023, 10:13am
2
There is no Group
tag in your xml, so Area
should have the fields of Group
directly. Also you need to use the #[serde(rename = "$value")]
tag for all fields you intend to store untagged values in. Currently you only use that attribute for scalar values, but it also applies to vectors.
This works parsing your xml file:
/*
[dependencies]
serde = { version = "1", features = ["derive"] }
serde-xml-rs = "*"
*/
#![allow(dead_code)]
use serde::Deserialize;
use serde_xml_rs;
#[derive(Debug, Deserialize)]
pub struct GC {
version: String,
endianness: String,
db_path: String,
#[serde(rename = "$value")]
gc: Vec<Sys>,
}
#[derive(Debug, Deserialize)]
struct Sys {
#[serde(rename = "$value")]
sys: Vec<Area>,
}
#[derive(Debug, Deserialize)]
struct Area {
name: Vec<Name>,
module: Vec<Module>,
}
#[derive(Debug, Deserialize)]
struct Name {
#[serde(rename = "$value")]
value: String,
}
#[derive(Debug, Deserialize)]
struct Module {
#[serde(rename = "$value")]
value: String,
}
fn main() {
let xml = r#"
<GC version="x.x.x" endianness="little" db_path="xxx/yyy/zzz">
<Sys>
<Area>
<name>AAA</name>
<name>CCC</name>
<module>BBB</module>
</Area>
</Sys>
<Sys>
<Area>
<name>AAA</name>
<module>BBB</module>
</Area>
</Sys>
</GC>
"#;
let foo: GC = serde_xml_rs::from_str(xml).unwrap();
println!("{foo:#?}");
}
Rustexplorer.
1 Like
CNier
March 25, 2023, 4:12pm
3
In the case i have
<GC version="x.x.x" endianness="little" db_path="xxx/yyy/zzz">
<Sys>
<Area>
<name>AAA</name>
<module>BBB</module>
</Area>
</Sys>
<Sys>
<Area>
<name>AAA</name>
<module>BBB</module>
</Area>
</Sys>
<Stz>
<Area>
<name>AAA</name>
<module>BBB</module>
</Area>
</Stz>
</GC>
Is there a way to define different struct with Sys and Stz? appearently it defines the struct below in the same way
jofas
March 25, 2023, 8:34pm
4
You can't combine both Stz
and Sys
tags in a struct but in an enum. This works for GC
containting both Sys
and Stz
tags:
/*
[dependencies]
serde = { version = "1", features = ["derive"] }
serde-xml-rs = "*"
*/
#![allow(dead_code)]
use serde::Deserialize;
use serde_xml_rs;
#[derive(Debug, Deserialize)]
pub struct GC {
version: String,
endianness: String,
db_path: String,
#[serde(rename = "$value")]
gc: Vec<GCContent>,
}
#[derive(Debug, Deserialize)]
enum GCContent {
Sys(Sys),
Stz(Stz),
}
#[derive(Debug, Deserialize)]
struct Sys {
#[serde(rename = "$value")]
sys: Vec<Area>,
}
#[derive(Debug, Deserialize)]
struct Stz {
#[serde(rename = "$value")]
stz: Vec<Area>,
}
#[derive(Debug, Deserialize)]
struct Area {
name: Vec<Name>,
module: Vec<Module>,
}
#[derive(Debug, Deserialize)]
struct Name {
#[serde(rename = "$value")]
value: String,
}
#[derive(Debug, Deserialize)]
struct Module {
#[serde(rename = "$value")]
value: String,
}
fn main() {
let xml = r#"
<GC version="x.x.x" endianness="little" db_path="xxx/yyy/zzz">
<Sys>
<Area>
<name>AAA</name>
<module>BBB</module>
</Area>
</Sys>
<Sys>
<Area>
<name>AAA</name>
<module>BBB</module>
</Area>
</Sys>
<Stz>
<Area>
<name>AAA</name>
<module>BBB</module>
</Area>
</Stz>
</GC>
"#;
let foo: GC = serde_xml_rs::from_str(xml).unwrap();
println!("{foo:#?}");
}
Rustexplorer.