I have the following XML, externally defined and outside of my organization's control:
<foo>
<bar>
<zip>zip</zip>
</bar>
<bar>
<zap>zap</zap>
</bar>
</foo>
I am using these structs:
type Foo struct {
XMLName xml.Name `xml:"foo"`
Bar1 Bar1
Bar2 Bar2
}
type Bar1 struct {
XMLName xml.Name `xml:"bar"`
Zip string `xml:"zip"`
}
type Bar2 struct {
XMLName xml.Name `xml:"bar"`
Zap string `xml:"zap"`
}
Because of the conflicting 'bar' name, nothing gets unmarshaled. How can I populate the Bar1 and Bar2 structs?
This is what I have: https://play.golang.org/p/D2IRLojcTB
This is the result I want: https://play.golang.org/p/Ytrbzzy9Ok
In the second one, I have updated the second 'bar' to be 'bar1,' and it all works. I'd rather come up with a cleaner solution that modifying the incoming XML.
The encoding/xml
package won't be able to do exactly what you want, since it makes the decision over which field of Foo
to decode into when it encounters the <bar>
element, rather than when processing children of that element. Your struct definitions make this decision ambiguous, as the error from xml.Unmarshal
indicates:
main.Foo field "Bar1" with tag "" conflicts with field "Bar2" with tag ""
Here are two alternatives that will work though:
1. Use one Bar
struct to cover both branches
If you modify your types to read as:
type Foo struct {
XMLName xml.Name `xml:"foo"`
Bars []Bar `xml:"bar"`
}
type Bar struct {
Zip string `xml:"zip"`
Zap string `xml:"zap"`
}
You will now get a slice that represents all the <bar>
elements. You can tell whether the element had a <zip>
or <zap>
element by checking whether the corresponding fields are non-empty.
You can try out this version here: https://play.golang.org/p/kguPCYmKX0
2. Use child selectors
If you are only interested in a single child element of <bar>
in each branch, then you might not need a struct to represent that element at all. For example, you could decode into the following type:
type Foo struct {
XMLName xml.Name `xml:"foo"`
Zip string `xml:"bar>zip"`
Zap string `xml:"bar>zap"`
}
Now the children of the <bar>
elements will be decoded directly into members of the Foo
struct. Note that with this option you won't be able to distinguish your chosen input from e.g.
<foo>
<bar>
<zip>zip</zip>
<zap>zap</zap>
</bar>
</foo>
If that will cause problems, then you should pick the first solution.
You can try out this version here: https://play.golang.org/p/fAE_HSrv4y
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With