serde-xml-rs
serde-xml-rs copied to clipboard
Unable to handle structure with different array values
Hello,
I modified the example slightly. Adding OtherItem into the Project structure give the following error:
thread 'it_works' panicked at 'called Result::unwrap()
on an Err
value: duplicate field Item
', /checkout/src/libcore/result.rs:859
Modified example:
#[macro_use] extern crate serde_derive;
extern crate serde_xml_rs;
use serde_xml_rs::deserialize;
#[derive(Debug, Deserialize)]
struct Item {
pub name: String,
pub source: String,
}
#[derive(Debug, Deserialize)]
struct OtherItem {
pub name: String,
}
#[derive(Debug, Deserialize)]
struct Project {
pub name: String,
#[serde(rename = "Item", default)]
pub items: Vec<Item>,
#[serde(rename = "OtherItem", default)]
pub other_items: Vec<OtherItem>,
}
#[test]
fn it_works() {
let s = r##"
<Project name="my_project">
<Item name="hello" source="world.rs" />
<OtherItem name="hello" source="world.rs" />
<Item name="hello" source="world.rs" />
</Project>
"##;
let project: Project = deserialize(s.as_bytes()).unwrap();
println!("{:#?}", project);
}
If I change the order of the items, it works:
<Project name="my_project">
<Item name="hello" source="world.rs" />
<Item name="hello" source="world.rs" />
<OtherItem name="hello" source="world.rs" />
</Project>
Is this a bug or is this how it is intended to work?
Unfortunately, this is how it's intended to work (at the moment). Serde's Deserializer trait is designed to work on streams and report items back as soon as they're found, so we can report only consecutive same-typed items as array. Otherwise, we would have to end up with keeping HashMap-based tree of entire XML before sending anything to Serde which would be quite expensive.
I understand. I am trying to parse wsdl files like this one: http://www.webservicex.com/CurrencyConvertor.asmx?wsdl And even in that small example the schema structure has an element which is followed by a simpleType and then two elements again.
Do you know of a workaround? Wouldn't holding information about the leaf and references to the parent chain be enough?
Huh, I truly hoped such examples don't exist in real-world :(
Wouldn't holding information about the leaf and references to the parent chain be enough?
The way I see, you need to always collect all children first before being able to report arrays to Serde (as you need to have both start and end when you do that). Which means that for each of their children you also need to deserialize their children first. And so on and so on... If you have a version which wouldn't involve such recursion, I'd happily accept a PR, it's just that personally I don't know how to do that without losing efficiency for other 95% of cases.
Do you know of a workaround?
Not sure if this works for you, but you can either 1) declare enum
and parse all children into such enum (where tag name is enum variant name and contents are, well, contents) or 2) you can implement custom deserialize function for such structure manually and use with Serde's deserialize_with
attribute.
Hi, thank you for great rust xml tool!
I have the same problem while writing my project.
The data is like below,
<link />
<joint />
<link />
<joint />
<link />
<joint />
and I want vector of link, and vector of joint.
If some one already solved this problem, could you show me how to handle it? That will help Rust/serde beginner like me!
This looks to be the same problem as: Repeated, Interleaved Tags are not working currently with serde. I made a proof of concept that will solve this. But it is not stable in any sense. https://github.com/RReverser/serde-xml-rs/issues/55 https://github.com/serde-rs/serde/issues/1725 https://github.com/ralpha/serde_deserializer_best_effort