我正在尝试创建一个实现MarshalXML输出的XML。 但目前我面临着几个问题。
我用于存储数据的结构是:
type Edition struct {
Launch string `xml:"launch" json:"launch"`
Code string `xml:"code" json:"code"`
Names []NameNode `xml:"names>name"`
Cards CardsComposition `xml:"cards" json:"cards,omitempty"`
Preconstructed PreconstructedInfo `xml:"preconstructed" json:"preconstructed,omitempty"`
Vault *struct{} `xml:"vault" json:"vault"`
Online *struct{} `xml:"online" json:"online"`
}
我想要的是:
如果未设置Preconstructed字段,请不要放置<preconstructed>
标记(即使它是空的,也使用它放置的标准封送器)。
所以我做的是:
func (preconstructed PreconstructedInfo) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if (PreconstructedInfo{} == preconstructed) {
return nil
}
return e.EncodeElement(preconstructed, start)
}
如果我用它来编码单个版本的实体,它显然是有效的。 但是如果我尝试编码一个Edition实体数组,我会收到以下错误:
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
(数组约200个条目)
所以我不明白的是:
答案 0 :(得分:4)
好的,我终于回答了自己,因为我终于解决了这个问题。
显然,其中一个问题是EncodeElement正在使用MarshalXML,并且使用庞大的文件会导致爆炸函数调用。
无论如何,解决方案是手动编码元素的所有组件。
所以在那种情况下我做到了:
// MarshalXML generate XML output for PrecsontructedInfo
func (preconstructed PreconstructedInfo) MarshalXML(e *xml.Encoder, start xml.StartElement) (err error) {
if (PreconstructedInfo{} == preconstructed) {
return nil
}
if preconstructed.Decks > 0 {
start.Attr = []xml.Attr{xml.Attr{Name: xml.Name{Local: "decks"}, Value: strconv.Itoa(preconstructed.Size)}}
}
if strings.Compare(preconstructed.Type, "") != 0 {
start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: "type"}, Value: preconstructed.Type})
}
err = e.EncodeToken(start)
e.EncodeElement(preconstructed.Size, xml.StartElement{Name: xml.Name{Local: "size"}})
return e.EncodeToken(xml.EndElement{Name: start.Name})
}
所以我做的是:
这样,只有在数据可用时才会生成xml标记,并且只有在有值的情况下才添加属性/子元素,如果它们为空或0则不添加。