dscojuxf69080 2014-12-17 21:00
浏览 0

使用(xpath)条件解组XML

I'm trying to unmarshall some XML which is structured like the following example:

<player>
 <stat type="first_name">Somebody</stat>
 <stat type="last_name">Something</stat>
 <stat type="birthday">06-12-1987</stat>
</player>

It's dead easy to unmarshal this into a struct like

type Player struct {
  Stats []Stat `xml:"stat"`
}

but I'm looking to find a way to unmarshal it into a struct that's more like

type Player struct {
  FirstName string `xml:"stat[@Type='first_name']"`
  LastName  string `xml:"stat[@Type='last_name']"`
  Birthday  Time   `xml:"stat[@Type='birthday']"`
}

is there any way to do this with the standard encoding/xml package? If not, can you give me a hint how one would split down such a "problem" in go? (best practices on go software architecture for such a task, basically).

thank you!

  • 写回答

1条回答 默认 最新

  • dpxbc88022 2014-12-18 15:07
    关注

    The encoding/xml package doesn't implement xpath, but does have a simple set of selection methods it can use.

    Here's an example of how you could unmarshal the XML you have using encoding/xml. Because the stats are all of the same type, with the same attributes, the easiest way to decode them will be into a slice of the same type. http://play.golang.org/p/My10GFiWDa

    var doc = []byte(`<player>
     <stat type="first_name">Somebody</stat>
     <stat type="last_name">Something</stat>
     <stat type="birthday">06-12-1987</stat>
    </player>`)
    
    type Player struct {
        XMLName xml.Name     `xml:"player"`
        Stats   []PlayerStat `xml:"stat"`
    }
    
    type PlayerStat struct {
        Type  string `xml:"type,attr"`
        Value string `xml:",chardata"`
    }
    

    And if it's something you need to transform often, you could do the transformation by using an UnamrshalXML method: http://play.golang.org/p/htoOSa81Cn

    type Player struct {
        XMLName   xml.Name `xml:"player"`
        FirstName string
        LastName  string
        Birthday  string
    }
    
    func (p *Player) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
        for {
            t, err := d.Token()
            if err == io.EOF {
                break
            } else if err != nil {
                return err
            }
    
            if se, ok := t.(xml.StartElement); ok {
    
                t, err = d.Token()
                if err != nil {
                    return err
                }
    
                var val string
                if c, ok := t.(xml.CharData); ok {
                    val = string(c)
                } else {
                    // not char data, skip for now
                    continue
                }
    
                // assuming we have exactly one Attr
                switch se.Attr[0].Value {
                case "first_name":
                    p.FirstName = val
                case "last_name":
                    p.LastName = val
                case "birthday":
                    p.Birthday = val
                }
            }
        }
        return nil
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 求帮我调试一下freefem代码
  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图