2
votes

I've got some XML that has a tag containing multiple sibling tags with the same name, like so:

<foo>
    <bar/>
    <bar/>
</foo>

(There may also be multiple top level <foo>s as well, though I've not gotten around to trying to (de)serialize that yet.)

Using this code:

use serde::{Deserialize, Serialize};
use quick_xml::de::from_str;
use quick_xml::se::to_string;

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct Foo {
    #[serde(rename = "bar", default)]
    bars: Vec<Bar>,
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename = "bar")]
struct Bar{

}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn deserialize_trivial_string_test() {
        let fs = "<foo><bar/><bar/></foo>";
        let foo = from_str(fs).unwrap();
        assert_eq!(Foo { bars: vec![Bar {}, Bar {}] }, foo);
    }

    #[test]
    fn serialize_trivial_string_test() {
        let foo = Foo { bars: vec![Bar {}, Bar {}] };
        let fs = to_string(&foo).unwrap();
        assert_eq!("<foo><bar/><bar/></foo>", fs);
    }
}

and don't forget to activate serialize feature:

[dependencies.quick-xml]
version = "0.18.1"
features = ["serialize"]

I can deserialize just fine, but serialization adds in an extra <bar> tag as the bars field wrapping the actual <bar> tags:

<Foo>
    <bar>
        <bar></bar>
        <bar></bar>
    </bar>
</Foo>

The #[serde(rename = "bar", default)] on the bars field was my first attempt to fix the this, based on quick-xml's documentation, but it obviously does not work. I also looked through serde's documentation, and did find a flatten attribute, but it did not seem to work when I tried applying it to the bars field.

Is there any way to get the serialization that I need, short of manually implementing Deserialize?

In case it's relevant, the actual data format I'm trying to work with is the flam3 file format. There's a sample file here. The <flame> element would be the equivalent to <foo> here, and <xform> is equivalent to <bar>.

1
just use flatten ? it's not clear what <bar/> is for me - Stargateur
@Stargateur As I stated in the question, I tried flatten. It didn't like the fact that the bars field is a Vec: "Err value: Custom("can only flatten structs and maps")'" - 8bittree
Isn't the result you get still valid ? I think you are expected to use docs.rs/quick-xml/0.18.1/quick_xml/struct.Writer.html if you want write as inner attribute. Or use a true data format like json :p - Stargateur
@Stargateur I'm not Scott Draves and it's not the early 90s, so I'm kind of stuck with the existing data format. And while the result is technically valid xml, it is does not have the correct structure. If you'll look closely at the before and after, you should see that the after has an extra <bar> element (from the renamed bars field) wrapping the actual <bar> elements. - 8bittree
I think you should ask on github of quick xml because except me there is not much people who answer serde question, and even less about xml format - Stargateur

1 Answers

0
votes

Unfortunately you can't. There is a outstanding issue on GitHub that addresses your question.