2013-09-29 56 views
3

我一直在玩Go的XML包,看不到下面的代碼有什麼問題。在Go中進行XML解碼

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\n", err) 
    } else { 
     decoded := xml.NewDecoder(res.Body) 

     err = decoded.Decode(items) 

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

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

上面的代碼運行沒有任何錯誤,並打印到終端:

Title: 

的結構似乎是空的,但我不明白爲什麼它不獲取XML數據填充。

回答

4

您的程序很接近,但需要指定更多的上下文來匹配XML文檔。

你需要修改你的字段標識,以幫助指導XML通過您 Channel結構結合到你Item結構:

type Channel struct { 
    Items []Item `xml:"channel>item"` 
} 

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

the documentation for encoding/xml.Unmarshal(),將第七顆子彈項適用於這裏:

如果XML元素包含名稱與 格式爲「a」或「a> b> c」的標籤的前綴相匹配的子元素,則解組 將下降到XML結構中cture正在尋找名稱爲 的元素,並將最內層的元素映射到該結構的 字段。以「>」開頭的標籤相當於一個起始 ,字段名稱後跟「>」。

在你的情況,你翻翻頂級<rss>元素的<channel>元下降到找到每個<item>元素。但是請注意,我們並不需要對一個實際上不能 - 指定由寫Items字段的標籤作爲

`xml:"rss>channel>item"` 

這方面是,Channel結構應通過頂層挖洞<rss>元素隱含的;提供給Unmarshall()的結構已映射到頂層XML元素。

還應注意,您Channel結構的Items場應該是類型片,OF- Item,不只是一個單一的Item的。


你提到你遇到麻煩的工作的建議。下面是我找到的作品正如人們所期望的完整列表:

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) 
     } 
    } 
} 
+0

這似乎很大,但現在我無法通過標籤訪問元素:http://pastebin.com/zzVN140s –

+1

請參閱上面我添加的源代碼清單。如果您對該提案仍有問題,請告知我們。 – seh

+1

完美,這很好,我現在在一個不錯的循環中。感謝一個負載,我將不得不進一步探討爲什麼將slice分配給一個變量,然後允許訪問struct字段。再次感謝:) –

4

我會完全明確這樣 - 命名所有的XML部分

See the playground for a full working example

type Rss struct { 
    Channel Channel `xml:"channel"` 
} 

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

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