I'm programming an xml response API in golang. Following the examples in the xml documentation it's pretty easy to create the xml giving them attributes and more.
The thing is that I need multiple tags under the same name and in different order.
<block>
<tag1>A Value1</tag1>
<tag2>B Value1</tag2>
<tag1>A Value2</tag1>
</block>
By creating a structure like
type Tag1 struct {
Value string `xml:",chardata"`
}
type Tag2 struct {
Value string `xml:",chardata"`
}
type Block struct {
XMLName xml.Name `xml:"block"`
Tags1 []Tag1 `xml:"tag1"`
Tags2 []Tag2 `xml:"tag2"`
}
I achieved this xml:
<block>
<tag1>A Value1</tag1>
<tag1>A Value2</tag1>
<tag2>B Value1</tag2>
</block>
That's due to the array type inside the block
definition. What I want, is a way to define that array type as an interface to inherit the two Tag
types. Like this
type Block struct {
XMLName xml.Name `xml:"block"`
Tags []Tags `xml:"tags"`
}
type (Tags t) Tag1 struct{
Value string `xml:",chardata"`
}
type (Tags t) Tag2 struct{
Value string `xml:",chardata"`
}
This way I could define the order of appearance in xml by the order of appending like
a1 := Tag1{"A Value1"}
b1 := Tag2{"B Value1"}
a2 := Tag1{"A Value2"}
arr := []Tags{}
arr = append(arr,a1)
arr = append(arr,b1)
arr = append(arr,a2)
v.Tags = arr
I've made some reading and I'm trying to avoid to implement the marshaling function used inside the xml package. Any help is appreciated, thanks.
I solved it differently. I just wasn't looking for the right approach. This question described what I needed. By defining the XMLName xml.Name
value in the Tag1
struct, I could define the name of the tag programmatically. And then just include the different Tags value with the old friend []interface{}
type.
type Tag1 struct {
XMLName xml.Name
Value string `xml:",chardata"`
}
type Block struct {
XMLName xml.Name `xml:"block"`
Tags []interface{}
}
a1 := Tag1{XMLName: xml.Name{Local: "tag1"}, Value: "A Value1"}
a2 := Tag1{XMLName: xml.Name{Local: "tag1"}, Value: "A Value2"}
b1 := Tag2{XMLName: xml.Name{Local: "tag2"}, Value: "B Value1"}
v := &Block{}
v.Tags = []interface{}{a1, b1, a2}
Check this example out to give it a play.