doumeng3080 2017-01-19 02:33
浏览 10
已采纳

通过父级属性动态解组子XML

How do we dynamically unmarshal child XML with attributes from parent?

We have the the following XMLs:

<!-- Report I -->
<report type="YYYY-MM-DD">
  <created_at>2016-01-01</created_at>
</report>

<!-- Report II -->
<report type="DD-MM-YYYY">
  <created_at>01-01-2016</created_at>
</report>

And we have the following structure:

type Report struct {
  XMLName   xml.Name    `xml:"report"`
  Type      string      `xml:"type,attr"`
  CreatedAt *ReportDate `xml:"created_at"`
}

type ReportDate struct {
    time.Time
}

func (c *ReportDate) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    const format = "02-01-2006" // or "2016-01-02" depending on parent's "type"
    var v string
    d.DecodeElement(&v, &start)
    parse, err := time.Parse(format, v)
    if err != nil {
        return err
    }
    *c = ReportDate{parse}
    return nil
}

Will it be possible for ReportDate to obtain type="?" from it's parent in UnmarshalXML? Or will it be possible for Report to pass down attribute values to all child tags? If it is possible, how do we accomplish this?

  • 写回答

2条回答 默认 最新

  • dongneng5383 2017-01-19 08:30
    关注

    While parsing the parent you can set a 'private' field within the child element that let's it know the time format string to use.

    Here's a working example https://play.golang.org/p/CEqjWoDQR3.

    And here's the code:

    package main
    
    import (
        "encoding/xml"
        "fmt"
        "io"
        "time"
    )
    
    // TypeMap converts the XML date format string to a valid Go date format string
    var typeMap = map[string]string{
        "YYYY-MM-DD": "2006-01-02",
        "DD-MM-YYYY": "02-01-2006",
    }
    
    // Example XML documents
    var reportStrings = []string{
        `<!-- Report I -->
    <report type="YYYY-MM-DD">
      <created_at>2016-01-01</created_at>
    </report>`,
    
        `<!-- Report II -->
    <report type="DD-MM-YYYY">
      <created_at>01-01-2016</created_at>
    </report>`,
    }
    
    type Report struct {
        XMLName   xml.Name   `xml:"report"`
        Type      string     `xml:"type,attr"`
        CreatedAt ReportDate `xml:"created_at"`
    }
    
    type ReportDate struct {
        dateFormatStr string // lower-case field is ignored by decoder/encoder
    
        Time time.Time
    }
    
    func (r *Report) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
        for _, attr := range start.Attr {
            if attr.Name.Local == "type" {
                dateFormatStr, ok := typeMap[attr.Value]
                if !ok {
                    return fmt.Errorf("unknown date type '%s'", attr.Value)
                }
                r.CreatedAt.dateFormatStr = dateFormatStr
            }
        }
    
        for {
            tok, err := d.Token()
            if err == io.EOF {
                break
            }
            if err != nil {
                return err
            }
            switch tok.(type) {
            case xml.StartElement:
                nextStart := tok.(xml.StartElement)
                if nextStart.Name.Local == "created_at" {
                    d.DecodeElement(&r.CreatedAt, &nextStart)
                }
            }
        }
    
        return nil
    }
    
    func (c *ReportDate) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
        var s string
        d.DecodeElement(&s, &start)
        t, err := time.Parse(c.dateFormatStr, s)
        if err != nil {
            return err
        }
        c.Time = t
        return nil
    }
    
    func main() {
        for i, reportStr := range reportStrings {
            var report Report
            if err := xml.Unmarshal([]byte(reportStr), &report); err != nil {
                panic(err)
            }
    
            fmt.Printf("[%d] %s
    ", i, report.CreatedAt.Time)
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题