#xml #go #unmarshalling
#xml #Вперед #отмена сопоставления
Вопрос:
У меня есть веб-служба, в которой я ожидаю получить два разных запроса; вызывается один, Request
содержащий только один Request
, а другой вызывается, RequestBulk
который содержит массив Request
s. Оба сопоставлены со структурами Golang следующим образом:
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"`
}
Разархивирование следующих XML-файлов работает должным образом:
<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>
Проблема
В RequestBulk
, если я изменю
Request []Request `xml:"Request,omitempty"`
Для
RequestMessage []Request `xml:"RequestMessage,omitempty"`
и измените XML на:
<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>
Я получаю следующую ошибку:
ожидаемый тип элемента <Request>, но имеющий <RequestMessage>
Очевидно, из-за XMLName xml.Name `xml:"https://item.com Request"`
Вопрос
Как мне сохранить Request
структуру без изменений и по-прежнему принимать сообщения типа RequestBulk
с другим именем для структуры Request
, а именно RequestMessage
?
Другими словами; Как мне использовать одну и ту же структуру с разными пространствами имен?
Запустите его на Go Playground.
Комментарии:
1. Ваш тип запроса включает в себя
XMLName
указание имени тегаRequest
. Если это не то, что вы хотите, удалите его.2. @Adrian Я знаю об этом, и я также упомянул об этом в сообщении. Вопрос начинается с прямо противоположного тому, что вы предложили. Пожалуйста, прочитайте вопрос еще раз!
3. Я сделал, но вы приняли ответ, который изменяет
Request
тип, добавляя к нему новый метод, поэтому сохранениеRequest
неизменным, похоже, не является жестким требованием.4. @Adrian да, он изменяет
Request
, но только в том случае, если имя являетсяRequestMessage
. Как упоминалось в начале моего вопроса, я хочу иметь возможность обрабатывать оба случая. Получение запросов с именемRequest
илиRequestMessage
. Знаете ли вы лучший способ сделать это?5. Вы можете обработать оба случая любым способом. Вам не нужен
XMLName
для единственногоRequest
варианта использования: play.golang.org/p/D1P1bVDADe7
Ответ №1:
Вы можете реализовать Unmarshaler
интерфейс для перезаписи локального имени элемента перед передачей элемента в декодер для фактического отмены сопоставления.
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), amp;start) // unmarshal
}