猿问

解析 xml 中的重复字段

我得到了一个 xml 响应,其中包含<Rights></Rights>块中的多个条目。它有几个<Name></Name>和<Access></Access>字段。


<?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


墨色风雨
浏览 232回答 1
1回答

温温酱

由于 XML 文档的布局,内置的封送规则无法将数据解码为给定的数据类型。以下是适用于您的文档的封送拆收器实现:package mainimport (&nbsp; &nbsp; "encoding/xml"&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "io"&nbsp; &nbsp; "log"&nbsp; &nbsp; "strconv")var data = []byte(`<?xml version="1.0" encoding="UTF-8"?>&nbsp; &nbsp; <SessionInfo>&nbsp; &nbsp; &nbsp; &nbsp;<SID>000000000000</SID>&nbsp; &nbsp; &nbsp; &nbsp;<Challenge>1337</Challenge>&nbsp; &nbsp; &nbsp; &nbsp;<BlockTime>0</BlockTime>&nbsp; &nbsp; &nbsp; &nbsp;<Rights>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Name>Dial</Name>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Access>2</Access>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Name>App</Name>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Access>2</Access>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Name>HomeAuto</Name>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Access>2</Access>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Name>BoxAdmin</Name>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Access>2</Access>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Name>Phone</Name>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Access>2</Access>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Name>NAS</Name>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Access>2</Access>&nbsp; &nbsp; &nbsp; &nbsp;</Rights>&nbsp; &nbsp; </SessionInfo>`)type sessionInfo struct {&nbsp; &nbsp; XMLName&nbsp; &nbsp;xml.Name `xml:"SessionInfo"`&nbsp; &nbsp; SID&nbsp; &nbsp; &nbsp; &nbsp;string&nbsp; &nbsp;`xml:"SID"`&nbsp; &nbsp; Challenge string&nbsp; &nbsp;`xml:"Challenge"`&nbsp; &nbsp; BlockTime uint&nbsp; &nbsp; &nbsp;`xml:"BlockTime"`&nbsp; &nbsp; Rights&nbsp; &nbsp; *rights&nbsp; `xml:"Rights"`}type rights struct {&nbsp; &nbsp; Rights []*right}type NameElement struct {&nbsp; &nbsp; XMLName xml.Name `xml:"Name"`&nbsp; &nbsp; Value&nbsp; &nbsp;string&nbsp; &nbsp;`xml:",chardata"`}type AccessElement struct {&nbsp; &nbsp; XMLName xml.Name `xml:"Access"`&nbsp; &nbsp; Value&nbsp; &nbsp;string&nbsp; &nbsp;`xml:",chardata"`}func (r *rights) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; var name NameElement&nbsp; &nbsp; &nbsp; &nbsp; var access AccessElement&nbsp; &nbsp; &nbsp; &nbsp; if err := d.Decode(&name); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err == io.EOF {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if err := d.Decode(&access); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; value, err := strconv.Atoi(access.Value)&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; r.Rights = append(r.Rights, &right{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name:&nbsp; &nbsp;name.Value,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Access: value,&nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; }&nbsp; &nbsp; return nil}func (r *rights) MarshalXML(e *xml.Encoder, start xml.StartElement) error {&nbsp; &nbsp; parentName := xml.Name{&nbsp; &nbsp; &nbsp; &nbsp; Local: "Rights",&nbsp; &nbsp; }&nbsp; &nbsp; parentStart := xml.StartElement{&nbsp; &nbsp; &nbsp; &nbsp; Name: parentName,&nbsp; &nbsp; }&nbsp; &nbsp; if err := e.EncodeToken(parentStart); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; }&nbsp; &nbsp; for _, right := range r.Rights {&nbsp; &nbsp; &nbsp; &nbsp; name := NameElement{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Value: right.Name,&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; value := AccessElement{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Value: strconv.Itoa(right.Access),&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if err := e.Encode(&name); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if err := e.Encode(&value); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; parentEnd := xml.EndElement{&nbsp; &nbsp; &nbsp; &nbsp; Name: parentName,&nbsp; &nbsp; }&nbsp; &nbsp; if err := e.EncodeToken(parentEnd); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return err&nbsp; &nbsp; }&nbsp; &nbsp; return nil}type right struct {&nbsp; &nbsp; Name&nbsp; &nbsp;string&nbsp; &nbsp; Access int}func main() {&nbsp; &nbsp; var result sessionInfo&nbsp; &nbsp; if err := xml.Unmarshal(data, &result); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatalln(err)&nbsp; &nbsp; }&nbsp; &nbsp; if out, err := xml.MarshalIndent(result, "", "&nbsp; "); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatalln(err)&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(string(out))&nbsp; &nbsp; }}https://play.golang.org/p/MK0RCfJo0a
随时随地看视频慕课网APP

相关分类

Go
我要回答