英文:
Correct use of XML annotations, fields and structs in custom UnmarshalXML function
问题
考虑以下结构体:
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{})
// ... 在这里进行 mxj 的操作 ...
myMxjMap, err := mxj.NewMapXml(v.Meta.Inner)
if err != nil {
return err
}
myMap = myMxjMap
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["meta"].(map[string]interface{})
我的问题是如何正确使用xml注释(innerxml
等)、字段和结构体,以便我不必手动在之后添加<meta></meta>
标签,就能将整个Meta字段作为一个单独的map。
完整的代码示例在这里:http://play.golang.org/p/Q4_tryubO6
英文:
Consider the following struct:
type MyStruct struct {
Name string
Meta map[string]interface{}
}
Which has the following UnmarshalXML function:
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
}
My problem with this code is these lines:
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{})
My question is how I make the correct use of the xml annotations (,innerxml etc), fields and structs, so I don't have to manually pre-/append the <meta></meta>
tags afterwards to get the whole Meta field as a single map.
The full code example is here: http://play.golang.org/p/Q4_tryubO6
答案1
得分: 5
xml
包没有提供一种将XML解组为map[string]interface{}
的方法,因为没有单一的方法来实现,并且在某些情况下是不可能的。map
不保留元素的顺序(这在XML中很重要),并且不允许具有重复键的元素。
你在示例中使用的mxj
包有一些规则,可以将任意的XML解组为Go map。如果你的要求与这些规则不冲突,你可以完全使用mxj
包进行所有解析,而不使用xml
包:
// 这里我省略了错误处理
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
英文:
xml
package doesn't provide a way to unmarshal XML into map[string]interface{}
because there is no single way to do it and in some cases it is not possible. A map doesn't preserve order of the elements (that is important in XML) and doesn't allow elements with duplicate keys.
mxj
package that you used in your example has some rules how to unmarshal arbitrary XML into Go map. If your requirements do not conflict with these rules you can use mxj
package to do all parsing and do not use xml
package at all:
// 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{})
Full example: http://play.golang.org/p/AcPUAS0QMj
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论