duanjingwei7239 2013-09-29 18:08
浏览 19
已采纳

Go中的XML解码

I've been playing about with Go's XML package and cannot see what is wrong with the following code.

package main

import (
    "encoding/xml"
    "fmt"
    "net/http"
) 

type Channel struct {
    Items Item
}

type Item struct {
    Title       string `xml:"title"`
    Link        string `xml:"link"`
    Description string `xml:"description"`
}

func main() {

    var items = new(Channel)
    res, err := http.Get("http://www.reddit.com/r/google.xml")

    if err != nil {
        fmt.Printf("Error: %v
", err)
    } else {
        decoded := xml.NewDecoder(res.Body)

        err = decoded.Decode(items)

        if err != nil {
            fmt.Printf("Error: %v
", err)
        }

        fmt.Printf("Title: %s
", items.Items.Title)
    }
}

The above code runs without any errors and prints to the terminal:

Title:

The struct seems empty but I can't see why it isn't getting populated with the XML data.

  • 写回答

2条回答 默认 最新

  • dsvd407787736 2013-09-29 19:01
    关注

    Your program comes close, but needs to specify just a little bit more context to match the XML document.

    You need to revise your field tags to help guide the XML binding down through your Channel structure to your Item structure:

    type Channel struct {
        Items []Item `xml:"channel>item"`
    }
    
    type Item struct {
        Title       string `xml:"title"`
        Link        string `xml:"link"`
        Description string `xml:"description"`
    }
    

    Per the documentation for encoding/xml.Unmarshal(), the seventh bullet item applies here:

    If the XML element contains a sub-element whose name matches the prefix of a tag formatted as "a" or "a>b>c", unmarshal will descend into the XML structure looking for elements with the given names, and will map the innermost elements to that struct field. A tag starting with ">" is equivalent to one starting with the field name followed by ">".

    In your case, you're looking to descend through the top-level <rss> element's <channel> elements to find each <item> element. Note, though, that we don't need to—an in fact can't—specify that the Channel struct should burrow through the top-level <rss> element by writing the Items field's tag as

    `xml:"rss>channel>item"`
    

    That context is implicit; the struct supplied to Unmarshall() already maps to the top-level XML element.

    Note too that your Channel struct's Items field should be of type slice-of-Item, not just a single Item.


    You mentioned that you're having trouble getting the proposal to work. Here's a complete listing that I find works as one would expect:

    package main
    
    import (
        "encoding/xml"
        "fmt"
        "net/http"
        "os"
    ) 
    
    type Channel struct {
        Items []Item `xml:"channel>item"`
    }
    
    type Item struct {
        Title       string `xml:"title"`
        Link        string `xml:"link"`
        Description string `xml:"description"`
    }
    
    func main() {
        if res, err := http.Get("http://www.reddit.com/r/google.xml"); err != nil {
            fmt.Println("Error retrieving resource:", err)
            os.Exit(1)
        } else {
            channel := Channel{}
            if err := xml.NewDecoder(res.Body).Decode(&channel); err != nil {
                fmt.Println("Error:", err)
                os.Exit(1)
            } else if len(channel.Items) != 0 {
                item := channel.Items[0]
                fmt.Println("First title:", item.Title)
                fmt.Println("First link:", item.Link)
                fmt.Println("First description:", item.Description)
            }
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料