I have a web service where I expect to receive two different requests; one is called Request
containing just one Request
and the other is called RequestBulk
which contains an array of Request
s. Both mapped to Golang structs as follows:
type RequestBulk struct {
XMLName xml.Name `xml:"https://item.com RequestBulk"`
Message string `xml:"Message"`
Request []Request `xml:"Request,omitempty"`
}
type Request struct {
XMLName xml.Name `xml:"https://item.com Request"`
Text string `xml:"text"`
}
Unmarshalling the following XMLs works as expected:
<Request xmlns="https://item.com">
<text>Some request text</text>
</Request>
<RequestBulk xmlns="https://item.com">
<Message>Some Text</Message>
<Request xmlns="https://item.com">
<text>Some request text</text>
</Request>
<Request xmlns="https://item.com">
<text>Some other request text</text>
</Request>
</RequestBulk>
In RequestBulk
, if I change
Request []Request `xml:"Request,omitempty"`
to
RequestMessage []Request `xml:"RequestMessage,omitempty"`
and change the XML to:
<RequestBulk xmlns="https://item.com">
<Message>Some Text</Message>
<RequestMessage xmlns="https://item.com">
<text>Some request text</text>
</RequestMessage>
<RequestMessage xmlns="https://item.com">
<text>Some other request text</text>
</RequestMessage>
</RequestBulk>
I get the following error:
expected element type <Request> but have <RequestMessage>
Obviously because of the XMLName xml.Name `xml:"https://item.com Request"`
How do I keep the Request
struct unchanged and still accept messages of type RequestBulk
with a different name for the struct Request
, namely, RequestMessage
?
In other words; How do I use the same struct with different namespaces?
Run it on Go Playground.
You can implement the Unmarshaler
interface to overwrite the element's local name before passing the element on to the decoder for the actual unmarshaling.
func (r *Request) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
if start.Name.Local == "RequestMessage" {
start.Name.Local = "Request" // overwrite
}
type tmp Request // avoid infinite recursive calls to Request.UnmarshalXML
return d.DecodeElement((*tmp)(r), &start) // unmarshal
}