drktvjp713333 2016-02-03 13:54 采纳率: 0%
浏览 28
已采纳

如何正确解析xml

I want to create structs = each type of command.

Commands have common part of xml - CommandResult. I created interface Command. I need to SomeCommand implements Command and can to be parsed as xml, also IsError must be realized in CommandResult, other functions must be realized by SomeCommand.

Code:

type Command interface {
    IsError() bool

    Request(buf *bufio.Writer, params interface{}) error
    ...
}

// Result of request
type CommandResult struct {
    Code    int    `xml:"code,attr" json:"code"`
    Message string `xml:"msg" json:"msg"`
}

// this Command's func is realized by CommandResult 
func (self CommandResult) IsError() bool {
    return true
}


// some command
type SomeCommand struct {
    CommandResult // CommandResult `xml:"response>result" json:"result"`
}

// this Command's func is realized by SomeCommand 
func (self SomeCommand) Request(buf *bufio.Writer, params interface{}) error {
    return nil
}

// other Command's functions are realized by CommandResult too

XML:

<epp>
  <response>
    <result code="1000">
      <msg>Command completed successfully</msg>
    </result>
    <trID>
      <svTRID>asd</svTRID>
    </trID>
  </response>
</epp>

Expected result:

a := SomeCommand
xml.NewDecoder(reader).Decode(&a)
// a.CommandResult.Code = 1000
// a.CommandResult.Message = 'Command completed successfully'

// a implements Command
  • 写回答

1条回答 默认 最新

  • duangao7133 2016-02-03 17:00
    关注
    1. I think paths in embedded structure should be absolute as all "parent's" structures are part of the "child". So your

       type CommandResult struct {
           Code    int    `xml:"code,attr" json:"code"`
           Message string `xml:"msg" json:"msg"`
       }
      

      Should be more like

       type CommandResult struct {
           Code    int    `xml:"response>result>code,attr" json:"code"`
           Message string `xml:"response>result>msg" json:"msg"`
       }
      

      BUT! There we are facing Go's limitation.

    2. You can't use attr with chaining. There is issue on Github but looks like it is not in priority list. So if I right understand shortest version of your CommandResult declaration would be:

      type CommandResult struct {
          Result struct {
              Code    int    `xml:"code,attr" json:"code"`
              Message string `xml:"msg" json:"msg"`
          } `xml:"response>result" json:"response"`
      }
      
    3. Not a real problem but in case if you will decide to convert Command back to XML would be nice to declare its XMLName. Something like

      type CommandResult struct {
          XMLName xml.Name `xml:"epp"`
          Result  struct {
              Code    int    `xml:"code,attr" json:"code"`
              Message string `xml:"msg" json:"msg"`
          } `xml:"response>result" json:"response"`
      }
      

      Because without it XML encoder will produce something like <SomeCommand><response>...</response></SomeCommand>

    Update with full example

    package main
    
    import (
        "bufio"
        "encoding/xml"
        "log"
    )
    
    type Command interface {
        IsError() bool
    
        Request(buf *bufio.Writer, params interface{}) error
    }
    
    // Result of request
    type CommandResult struct {
        XMLName xml.Name `xml:"epp"`
        Result  struct {
            Code    int    `xml:"code,attr" json:"code"`
            Message string `xml:"msg" json:"msg"`
        } `xml:"response>result" json:"response"`
    }
    
    // this Command's func is realized by CommandResult
    func (self CommandResult) IsError() bool {
        return true
    }
    
    // some command
    type SomeCommand struct {
        CommandResult
    }
    
    // this Command's func is realized by SomeCommand
    func (self SomeCommand) Request(buf *bufio.Writer, params interface{}) error {
        return nil
    }
    
    type AnotherCommand struct {
        CommandResult
    }
    
    func (self AnotherCommand) Request(buf *bufio.Writer, params interface{}) error {
        return nil
    }
    
    func main() {
        var c Command
    
        c = SomeCommand{}
        log.Println(c.IsError())
    
        c = AnotherCommand{}
        log.Println(c.IsError())
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?