为了账号安全,请及时绑定邮箱和手机立即绑定

解析 xml 中的重复字段

解析 xml 中的重复字段

Go
墨色风雨 2022-04-20 17:52:42
我得到了一个 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
查看完整描述

1 回答

?
温温酱

TA贡献1752条经验 获得超4个赞

由于 XML 文档的布局,内置的封送规则无法将数据解码为给定的数据类型。


以下是适用于您的文档的封送拆收器实现:


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


查看完整回答
反对 回复 2022-04-20
  • 1 回答
  • 0 关注
  • 231 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信