Правильное использование аннотаций, полей и структур 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