2016-11-13 85 views
0

我收到了一個xml響應,其中包含<Rights></Rights>塊中的多個條目。它有幾個<Name></Name><Access></Access>字段。解析xml中的字段

<?xml version="1.0" encoding="UTF-8"?> 
<SessionInfo> 
    <SID>000000000000</SID> 
    <Challenge>1337</Challenge> 
    <BlockTime>0</BlockTime> 
    <Rights> 
     <Name>Dial</Name> 
     <Access>2</Access> 
     <Name>App</Name> 
     <Access>2</Access> 
     <Name>HomeAuto</Name> 
     <Access>2</Access> 
     <Name>BoxAdmin</Name> 
     <Access>2</Access> 
     <Name>Phone</Name> 
     <Access>2</Access> 
     <Name>NAS</Name> 
     <Access>2</Access> 
    </Rights> 
</SessionInfo> 

我想將此轉換爲一個權利結構。

type sessionInfo struct { 
    XMLName xml.Name `xml:"SessionInfo"` 
    SID  string `xml:"SID"` 
    Challenge string `xml:"Challenge"` 
    BlockTime uint  `xml:"BlockTime"` 
    Rights  []rights `xml:"Rights"` 
} 

type rights struct { 
    Name string `xml:"Name"` 
    Access int `xml:"Access"` 
} 

不幸的是,它只寫入最後一個元素到數組中。無需編寫自己的解碼器,是否可以在Go中執行此操作?

<SessionInfo> 
    <SID>000000000000</SID> 
    <Challenge>1337</Challenge> 
    <BlockTime>0</BlockTime> 
    <Rights> 
     <Name>NAS</Name> 
     <Access>2</Access> 
    </Rights> 
</SessionInfo> 

你可以在這裏測試:https://play.golang.org/p/29I2GPttOz

回答

3

由於XML文檔的佈局,內置編組規則不能對數據進行解碼到你給出的數據類型。

下面是一個封送和unmarshaler實現,應爲您的文檔工作:

package main 

import (
    "encoding/xml" 
    "fmt" 
    "io" 
    "log" 
    "strconv" 
) 

var data = []byte(`<?xml version="1.0" encoding="UTF-8"?> 
    <SessionInfo> 
     <SID>000000000000</SID> 
     <Challenge>1337</Challenge> 
     <BlockTime>0</BlockTime> 
     <Rights> 
      <Name>Dial</Name> 
      <Access>2</Access> 
      <Name>App</Name> 
      <Access>2</Access> 
      <Name>HomeAuto</Name> 
      <Access>2</Access> 
      <Name>BoxAdmin</Name> 
      <Access>2</Access> 
      <Name>Phone</Name> 
      <Access>2</Access> 
      <Name>NAS</Name> 
      <Access>2</Access> 
     </Rights> 
    </SessionInfo>`) 

type sessionInfo struct { 
    XMLName xml.Name `xml:"SessionInfo"` 
    SID  string `xml:"SID"` 
    Challenge string `xml:"Challenge"` 
    BlockTime uint  `xml:"BlockTime"` 
    Rights *rights `xml:"Rights"` 
} 

type rights struct { 
    Rights []*right 
} 

type NameElement struct { 
    XMLName xml.Name `xml:"Name"` 
    Value string `xml:",chardata"` 
} 
type AccessElement struct { 
    XMLName xml.Name `xml:"Access"` 
    Value string `xml:",chardata"` 
} 

func (r *rights) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { 
    for { 
     var name NameElement 
     var access AccessElement 
     if err := d.Decode(&name); err != nil { 
      if err == io.EOF { 
       break 
      } 
      return err 
     } 
     if err := d.Decode(&access); err != nil { 
      return err 
     } 
     value, err := strconv.Atoi(access.Value) 
     if err != nil { 
      return err 
     } 
     r.Rights = append(r.Rights, &right{ 
      Name: name.Value, 
      Access: value, 
     }) 
    } 
    return nil 
} 

func (r *rights) MarshalXML(e *xml.Encoder, start xml.StartElement) error { 

    parentName := xml.Name{ 
     Local: "Rights", 
    } 

    parentStart := xml.StartElement{ 
     Name: parentName, 
    } 

    if err := e.EncodeToken(parentStart); err != nil { 
     return err 
    } 

    for _, right := range r.Rights { 
     name := NameElement{ 
      Value: right.Name, 
     } 
     value := AccessElement{ 
      Value: strconv.Itoa(right.Access), 
     } 
     if err := e.Encode(&name); err != nil { 
      return err 
     } 
     if err := e.Encode(&value); err != nil { 
      return err 
     } 
    } 

    parentEnd := xml.EndElement{ 
     Name: parentName, 
    } 
    if err := e.EncodeToken(parentEnd); err != nil { 
     return err 
    } 

    return nil 
} 

type right struct { 
    Name string 
    Access int 
} 

func main() { 
    var result sessionInfo 
    if err := xml.Unmarshal(data, &result); err != nil { 
     log.Fatalln(err) 
    } 

    if out, err := xml.MarshalIndent(result, "", " "); err != nil { 
     log.Fatalln(err) 
    } else { 
     fmt.Println(string(out)) 
    } 
} 

https://play.golang.org/p/MK0RCfJo0a