以前書いた「Goでニコニコ生放送のRSSから開場日時や放送開始日時を抽出してみる」の改良版です。
xml.Unmarshal
関数に渡す構造体のフィールドの型は通常はstring
しか指定できませんが、こう書けば別の型も使えます。
parsenicoliverss.go
package main
import (
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"time"
)
// (1)まずtime.Timeを含む構造体を作って
type CustomTime struct {
time.Time
}
// (2)UnmarshalXMLメソッドを実装する(xml.Unmarshalerインターフェースに定義されているメソッド)
func (c *CustomTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var v string
d.DecodeElement(&v, &start)
parse, err := time.Parse("2006-01-02 15:04:05 MST", fmt.Sprintf("%s JST", v))
if err != nil {
return err
}
*c = CustomTime{parse}
return nil
}
type Item struct {
XMLName xml.Name `xml:"item"`
Title string `xml:"title"`
Description string `xml:"description"`
// (3)日時を表すフィールドは上記のCustomTimeを使う
OpenTime CustomTime `xml:"http://live.nicovideo.jp/ open_time"`
StartTime CustomTime `xml:"http://live.nicovideo.jp/ start_time"`
}
type Channel struct {
XMLName xml.Name `xml:"channel"`
Title string `xml:"title"`
Items []Item `xml:"item"`
}
type Rss struct {
XMLName xml.Name `xml:"rss"`
Channel Channel `xml:"channel"`
}
func main() {
res, err := http.Get("http://live.nicovideo.jp/rss")
if err != nil {
panic(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
r := Rss{}
if err := xml.Unmarshal(body, &r); err != nil {
panic(err)
}
fmt.Printf("RSSタイトル: %s\n", r.Channel.Title)
fmt.Println("----------")
for _, v := range r.Channel.Items {
fmt.Printf("番組タイトル: %s\n", v.Title)
fmt.Printf("番組説明文: %s\n", v.Description)
fmt.Printf("開場日時: %s\n", v.OpenTime)
fmt.Printf("放送開始日時: %s\n", v.StartTime)
fmt.Println("----------")
}
}
参考: xml parsing - Golang XML Unmarshal and time.Time fields - Stack Overflow