2016-05-12 50 views
2

时如何省略走空场,我有以下结构:生成XML

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仍然包含空的“custom-attributes”标签?

<custom-attributes></custom-attributes> 

回答

1

一个解决方案是使CustomAttributes字段成为指针。当值为nil时,它将被省略。在Marshal文档中查找“零值”。

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"}, 
     }, 
    }) 
} 

Playground

2

我想在这里发生的是,因为你指定的元素的名称嵌套,custom-attributes>custom-attribute那种隐含的“外”的(“中间”?“容器”? )元素,custom-attributes应该存在—部分原因是因为没有任何东西阻止您使用名称标记任何数量的其他字段,包括像custom-attributes>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, 
    }) 
} 

Playground link

+0

我喜欢这两种解决方案(你和我接受的答案),他们很好学习如何实现,但因为我只能选择一个答案,我选择了顶部的答案(根据StackOverflow如何排序)。谢谢。 – daniels