Correct use of XML annotations, fields and structs in custom UnmarshalXML function

huangapple go评论73阅读模式
英文:

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:&quot;myStruct&quot;`
		Name    string   `xml:&quot;name&quot;`
		Meta    struct {
			Inner []byte `xml:&quot;,innerxml&quot;`
		} `xml:&quot;meta&quot;`
	}

	err := d.DecodeElement(&amp;v, &amp;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 := &quot;&lt;meta&gt;&quot;
	postfix := &quot;&lt;/meta&gt;&quot;
	str := prefix + string(temp) + postfix
	//fmt.Println(str)
	myMxjMap, err := mxj.NewMapXml([]byte(str))
	myMap = myMxjMap

	// fill myMap
	//m.Meta = myMap
	m.Meta = myMap[&quot;meta&quot;].(map[string]interface{})
	return nil
}

My problem with this code is these lines:

prefix := &quot;&lt;meta&gt;&quot;
postfix := &quot;&lt;/meta&gt;&quot;
str := prefix + string(temp) + postfix
myMxjMap, err := mxj.NewMapXml([]byte(str))
myMap = myMxjMap
//m.Meta = myMap
m.Meta = myMap[&quot;meta&quot;].(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 &lt;meta&gt;&lt;/meta&gt; 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[&quot;myStruct&quot;].(map[string]interface{})
myStruct.Name = mm[&quot;name&quot;].(string)
myStruct.Meta = mm[&quot;meta&quot;].(map[string]interface{})

Full example: http://play.golang.org/p/AcPUAS0QMj

huangapple
  • 本文由 发表于 2015年7月2日 14:31:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/31177050.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定