2016-11-13 7 views
0

<Rights></Rights>ブロックに複数のエントリを含むxml応答があります。いくつかのフィールドがある。<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> 

あなたがここにこれをテストすることができますため、XML文書のレイアウトにhttps://play.golang.org/p/29I2GPttOz

答えて

3

、内蔵のあなたの特定のデータ型にデータをデコードすることができないルールをマーシャリング。

以下

ドキュメントのために働く必要がありますマーシャラーと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

関連する問題