英文:
xml mischief when using structs containing slices?
问题
我尝试了以下代码,以便理解为什么在使用golang中的xml时会遇到问题。
据我了解,我应该能够将一个结构体进行编组,然后将结果数据解组回相同类型的结构体中?
我期望的结果是一个包含子结构体切片的父结构体,但实际上子结构体切片是空的?
package main
import (
"encoding/xml"
"fmt"
)
type Parent struct {
XMLName xml.Name `xml:"parent"`
Children []Child `xml:"children"`
}
type Child struct {
XMLName xml.Name `xml:"child"`
ID int `xml:"ID"`
}
func main() {
children := make([]Child, 3)
for i := range children {
children[i] = Child{ID: i}
}
p1 := Parent{Children: children}
data, err := xml.Marshal(p1)
if err != nil {
fmt.Printf("Error during marshal: %v\n", err)
}
fmt.Printf("Raw XML: %v\n", string(data))
p2 := Parent{}
err = xml.Unmarshal(data, &p2)
if err != nil {
fmt.Printf("Error during unmarshal: %v\n", err)
}
fmt.Printf("Unmarshalled struct: %v\n", p2)
}
英文:
I tried the following code in an effort to understand why I'm having issues with my xml in golang.
As I understand it, I should be able to marshal a struct and then unmarshal the resulting data back into a struct of the same type?
Result I expected is a parent struct containing a slice of childs, instead that children slice is nil?
package main
import (
"encoding/xml"
"fmt"
)
type Parent struct {
XMLName xml.Name `xml:"parent"`
Children []Child `xml:"children"`
}
type Child struct {
XMLName xml.Name `xml:"child"`
ID int `xml:"ID"`
}
func main() {
children := make([]Child, 3)
for i := range children {
children[i] = Child{ID: i}
}
p1 := Parent{Children: children}
data, err := xml.Marshal(p1)
if err != nil {
fmt.Printf("Error during marshal: %v\n", err)
}
fmt.Printf("Raw XML: %v\n", string(data))
p2 := Parent{}
err = xml.Unmarshal(data, &p2)
if err != nil {
fmt.Printf("Error during unmarshal: %v\n", err)
}
fmt.Printf("Unmarshalled struct: %v\n", p2)
}
答案1
得分: 1
它不完全像这样工作:结构体和XML之间没有特定的双射关系。
例如,你生成了以下XML:
<parent><child><ID>0</ID></child><child><ID>1</ID></child></parent>
这是因为你的Child
类型有一个带有XML标签"child"的字段XMLName xml.Name
。
这就是编组的工作原理。参考自http://tip.golang.org/pkg/encoding/xml/#Marshal
XML元素的名称按照以下优先顺序确定:
- XMLName字段上的标签(如果数据是结构体)
- 类型为xml.Name的XMLName字段的值
- 用于获取数据的结构体字段的标签
- 用于获取数据的结构体字段的名称
- 序列化类型的名称
现在看看如果你尝试解组它会发生什么:
你的Parent
类型使用"children"标记其字段Children []Child
,但是你的XML中根本没有<children>
标签,只有<child>
。
如果你使用
type Parent struct {
XMLName xml.Name `xml:"parent"`
Children []Child `xml:"child"` // 使用"child",而不是"children"
}
它会按照你的意图正常工作。
英文:
It doesn't work quite like this: There is no ad hoc bijection between a struct and a XML.
E.g. you generate the following XML
<parent><child><ID>0</ID></child><child><ID>1</ID></child></parent>
because your Child
type has a field XMLName xml.Name
with a xml tag "child".
That's how Marshaling works. From http://tip.golang.org/pkg/encoding/xml/#Marshal
> The name for the XML elements is taken from, in order of preference:
>
> - the tag on the XMLName field, if the data is a struct
> - the value of the XMLName field of type xml.Name
> - the tag of the struct field used to obtain the data
> - the name of the struct field used to obtain the data
> - the name of the marshalled type
Now take a look what happens if you try to Unmarshal it:
Your Parent
type tags its field Children []Child
with "children"
but your XML simply has no <children>
tag inside, only <child>
.
If you use
type Parent struct {
XMLName xml.Name `xml:"parent"`
Children []Child `xml:"child"` // "child", not "children"
}
it works like you intended.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论