【发布时间】:2019-12-02 19:07:55
【问题描述】:
我需要解析具有动态元素的 XML 消息,因此我使用了 interface{} 类型的元素在我的 Message 结构中表示它。
一旦我知道了这个动态元素的类型(在运行时),我就会初始化一个消息结构,然后尝试解组 XML 消息。但是,动态元素的内容并未解组。
这是一个 Go Playground,其中包含我想要实现的目标,包括 cmets 以及实际与预期的输出:https://play.golang.org/p/eKVetUPmVI2
我尝试了几种变体,但无法让解组按预期工作。谁能帮我理解为什么这种行为以及如何使它起作用?提前致谢。
代码(以防 Go Playground 链接有一天中断):
package main
import "fmt"
import "encoding/xml"
// XML root
type Message struct {
XMLName xml.Name `xml:"message"`
Operation Operation `xml:"operation"`
}
// An Operation can contain either a Create or an Update element
type Operation struct {
Create *Create `xml:"create"`
Update *Update `xml:"update"`
}
// Doesn't matter...
type Create struct{}
// Update contains a Color element or Any other element (we only know its type during runtime)
type Update struct {
Color *Color `xml:"color"`
Other Any
}
// Doesn't matter...
type Color struct{}
type Any interface{}
var xmlStr = []byte(`<message>
<operation>
<update>
<size>
<width>1000</width>
</size>
</update>
</operation>
</message>`)
func main() {
// At this point we already know what to expect to receive in Other, so we can declare a struct for its content (Size)
type Size struct {
XMLName xml.Name `xml:"size"`
Width string `xml:"width"`
}
// Unmarshal
msg := &Message{
Operation: Operation{
Update: &Update{
Other: &Size{}, // Here I'm setting Other to Size, so I would expect Go to unmarshal the <size> contents into it
},
},
}
if err := xml.Unmarshal(xmlStr, msg); err != nil {
fmt.Println(err)
}
// Marshal again
b, err := xml.MarshalIndent(msg, "", " ")
if err != nil {
fmt.Println(err)
}
fmt.Printf("expected:\n\n%s\n\n", xmlStr)
fmt.Printf("actual:\n\n%s", string(b))
}
【问题讨论】:
标签: go