2016-05-12 8 views
2

Ich habe folgende Struktur:Wie leere Felder in GO wegzulassen, wenn XML-Erzeugung

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"` 
} 

und dann initialisiere ich die Struktur wie folgt:

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], 
    } 

So ist die Custom Array immer leer ist, und len (store.CustomAttributes) ist 0, also irgendeine Idee, warum das generierte XML immer noch das leere "custom-attributes" -Tag enthält?

<custom-attributes></custom-attributes> 

Antwort

1

Eine Lösung besteht darin, das Feld CustomAttributes einen Zeiger zu machen. Es wird weggelassen, wenn der Wert nil ist. Suchen Sie in der Dokumentation Marshal nach "Nullwerten".

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

Ich denke, was das hier passiert ist, da Sie den Namen des Elements als verschachtelt, diese Art von custom-attributes>custom-attribute der „äußeren“ angegeben impliziert („intermediate“ ?, „Container“?) Element, custom-attributes sollte — zum Teil, weil nichts verhindert, dass Sie eine beliebige Anzahl von anderen Feldern mit Namen einschließlich des gleichen äußeren Elements — wie Tagging.

Tracking der Fall keines dieser Felder wurden gemarshallte und damit deren äußere Element sollte nicht verwendet werden, ist wahrscheinlich zu viel für die Marshaler die — Ich nehme an — explizit als weniger Kontext wie möglich zu halten geschrieben, während es funktioniert.

Daher, während ich verstehe, dass Sie verwirrt sind, denke ich, dieses Verhalten ist verständlich, wenn Sie es ein bisschen länger schielen.

Betreffs, was über die Lösung, es zu tun, würde ich persönlich versuchen expliziter zu sein und wickelte Ihre Scheibe in eine struct Art, wie mit

type CustomAttributes struct { 
    XMLName xml.Name `xml:"custom-attributes"` 
    Items []CustomAttribute `xml:"custom-attributes>custom-attribute"` 
} 

und dann eine benutzerdefinierte Marshall auf sie haben würde :

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

Ich mag beide Lösungen (Ihre und die Antwort, die ich akzeptiere) und sie sind großartig zu lernen, wie Dinge implementiert werden können, aber da ich nur eine Antwort auswählen kann, wählte ich die am oberen Ende (basierend darauf, wie StackOverflow sie sortiert). Vielen Dank. – daniels

Verwandte Themen