生成XML时如何省略GO中的空字段
我有以下结构:生成XML时如何省略GO中的空字段,xml,go,Xml,Go,我有以下结构: type CustomAttribute struct { Id string `xml:"attribute-id,attr,omitempty"` Values []string `xml:"value,omitempty"` } type Store struct { XMLName xml.Name `xml:"store"` Id string
type CustomAttribute struct {
Id string `xml:"attribute-id,attr,omitempty"`
Values []string `xml:"value,omitempty"`
}
type Store struct {
XMLName xml.Name `xml:"store"`
Id string `xml:"store-id,attr,omitempty"`
Name string `xml:"name,omitempty"`
Address1 string `xml:"address1,omitempty"`
Address2 string `xml:"address2,omitempty"`
City string `xml:"city,omitempty"`
PostalCode string `xml:"postal-code,omitempty"`
StateCode string `xml:"state-code,omitempty"`
CountryCode string `xml:"country-code,omitempty"`
Phone string `xml:"phone,omitempty"`
Lat float64 `xml:"latitude,omitempty"`
Lng float64 `xml:"longitude,omitempty"`
CustomAttributes []CustomAttribute `xml:"custom-attributes>custom-attribute,omitempty"`
}
然后我初始化结构,如下所示:
store := &Store{
Id: storeId,
Name: row[4],
Address1: row[5],
Address2: row[6],
City: row[7],
PostalCode: row[9],
StateCode: row[8],
CountryCode: row[11],
Phone: row[10],
}
所以CustomAttributes数组总是空的,len(store.CustomAttributes)是0,那么你知道为什么生成的XML仍然包含空的“CustomAttributes”标记吗
一种解决方案是将
CustomAttributes
字段设置为指针。当值为nil
时,它将被忽略。在文档中查找“零值”
package main
import (
"encoding/xml"
"fmt"
"log"
)
type Store struct {
XMLName xml.Name `xml:"store"`
CustomAttributes *[]CustomAttribute `xml:"custom-attributes>custom-attribute,omitempty"`
}
type CustomAttribute struct {
Id string `xml:"attribute-id,attr,omitempty"`
Values []string `xml:"value,omitempty"`
}
func print(store *Store) {
data, err := xml.Marshal(store)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
}
func main() {
print(&Store{})
print(&Store{
CustomAttributes: &[]CustomAttribute{},
})
print(&Store{
CustomAttributes: &[]CustomAttribute{
{Id: "hello"},
},
})
}
我认为这里发生的是,由于您将元素的名称指定为嵌套的,
自定义属性>自定义属性
在某种程度上暗示了“outer”(“intermediate”、“container”)元素,自定义属性
应该存在,部分原因是没有任何东西可以阻止您使用包含相同外部元素的名称标记任何数量的其他字段,如自定义属性>foobar
跟踪这种情况,没有一个这样的字段被封送,因此不应该使用它们的外部元素,这对于封送器来说可能太多了,我想,封送器是显式编写的,以便在工作时保持尽可能少的上下文
因此,虽然我理解你感到困惑,但我认为这种行为是可以理解的,只要你眯着眼睛看得久一点
至于如何解决这个问题,我个人会尽量说得更清楚
并将切片包装成struct
类型,如
type CustomAttributes struct {
XMLName xml.Name `xml:"custom-attributes"`
Items []CustomAttribute `xml:"custom-attributes>custom-attribute"`
}
然后会有一个自定义封送拆收器:
func (cas CustomAttributes) MarshalXML(e *xml.Encoder,
start xml.StartElement) (err error) {
if len(cas.Items) == 0 {
return nil
}
err = e.EncodeToken(start)
if err != nil {
return
}
err = e.Encode(cas.Items)
if err != nil {
return
}
return e.EncodeToken(xml.EndElement{
Name: start.Name,
})
}
.我喜欢这两种解决方案(您的和我接受的答案),它们非常适合学习如何实施,但由于我只能选择一个答案,因此我选择了顶部的答案(基于StackOverflow对它们的排序)。谢谢
func (cas CustomAttributes) MarshalXML(e *xml.Encoder,
start xml.StartElement) (err error) {
if len(cas.Items) == 0 {
return nil
}
err = e.EncodeToken(start)
if err != nil {
return
}
err = e.Encode(cas.Items)
if err != nil {
return
}
return e.EncodeToken(xml.EndElement{
Name: start.Name,
})
}