Правильное использование аннотаций, полей и структур XML в пользовательской функции UnmarshalXML
Рассмотрим следующую структуру:
type MyStruct struct {
Name string
Meta map[string]interface{}
}
Что имеет следующую функцию UnmarshalXML:
func (m *MyStruct) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var v struct {
XMLName xml.Name //`xml:"myStruct"`
Name string `xml:"name"`
Meta struct {
Inner []byte `xml:",innerxml"`
} `xml:"meta"`
}
err := d.DecodeElement(&v, &start)
if err != nil {
return err
}
m.Name = v.Name
myMap := make(map[string]interface{})
// ... do the mxj magic here ... -
temp := v.Meta.Inner
prefix := "<meta>"
postfix := "</meta>"
str := prefix + string(temp) + postfix
//fmt.Println(str)
myMxjMap, err := mxj.NewMapXml([]byte(str))
myMap = myMxjMap
// fill myMap
//m.Meta = myMap
m.Meta = myMap["meta"].(map[string]interface{})
return nil
}
Моя проблема с этим кодом заключается в следующих строках:
prefix := "<meta>"
postfix := "</meta>"
str := prefix + string(temp) + postfix
myMxjMap, err := mxj.NewMapXml([]byte(str))
myMap = myMxjMap
//m.Meta = myMap
m.Meta = myMap["meta"].(map[string]interface{})
Мой вопрос заключается в том, как я правильно использую аннотации xml (, innerxml и т.д.), поля и структуры, поэтому мне не нужно вручную предварительно/добавлять теги <meta></meta>
впоследствии, чтобы получить все поле Meta как единую карту.
Полный пример кода приведен здесь: http://play.golang.org/p/Q4_tryubO6
Ответы
Ответ 1
xml
пакет не предоставляет способ развязать XML в map[string]interface{}
, потому что нет единственного способа сделать это, а в некоторых случаях это невозможно. Карта не сохраняет порядок элементов (что важно в XML) и не позволяет элементам с дублирующимися ключами.
mxj
, который вы использовали в вашем примере, есть некоторые правила, как размонтировать произвольный XML в карту Go. Если ваши требования не противоречат этим правилам, вы можете использовать пакет mxj
для выполнения всего разбора и вообще не использовать пакет xml
:
// I am skipping error handling here
m, _ := mxj.NewMapXml([]byte(s))
mm := m["myStruct"].(map[string]interface{})
myStruct.Name = mm["name"].(string)
myStruct.Meta = mm["meta"].(map[string]interface{})
Полный пример: http://play.golang.org/p/AcPUAS0QMj