2009-11-23 12:46:12 +00:00
|
|
|
package feeder
|
|
|
|
|
2013-10-26 03:26:15 +00:00
|
|
|
import (
|
|
|
|
xmlx "github.com/jteeuwen/go-pkg-xmlx"
|
|
|
|
)
|
2009-11-23 12:46:12 +00:00
|
|
|
|
2014-09-25 12:27:05 +00:00
|
|
|
type MissingRssNodeError struct{}
|
|
|
|
|
|
|
|
func (err *MissingRssNodeError) Error() string { return "Failed to find rss/rdf node in XML." }
|
|
|
|
|
2014-01-18 14:30:56 +00:00
|
|
|
type Extension struct {
|
|
|
|
Name string
|
|
|
|
Value string
|
|
|
|
Attrs map[string]string
|
2014-01-23 16:57:26 +00:00
|
|
|
Childrens map[string][]Extension
|
2014-01-18 14:30:56 +00:00
|
|
|
}
|
|
|
|
|
2013-12-05 12:53:57 +00:00
|
|
|
var days = map[string]int{
|
|
|
|
"Monday": 1,
|
|
|
|
"Tuesday": 2,
|
|
|
|
"Wednesday": 3,
|
|
|
|
"Thursday": 4,
|
|
|
|
"Friday": 5,
|
|
|
|
"Saturday": 6,
|
|
|
|
"Sunday": 7,
|
|
|
|
}
|
|
|
|
|
2011-11-02 15:51:04 +00:00
|
|
|
func (this *Feed) readRss2(doc *xmlx.Document) (err error) {
|
2013-12-05 13:05:24 +00:00
|
|
|
var foundChannels []*Channel
|
2010-12-17 23:25:16 +00:00
|
|
|
var ch *Channel
|
|
|
|
var i *Item
|
|
|
|
var n *xmlx.Node
|
|
|
|
var list, tl []*xmlx.Node
|
2011-02-01 14:30:39 +00:00
|
|
|
const ns = "*"
|
2010-12-17 23:25:16 +00:00
|
|
|
|
2013-10-26 03:26:15 +00:00
|
|
|
root := doc.SelectNode(ns, "rss")
|
|
|
|
if root == nil {
|
|
|
|
root = doc.SelectNode(ns, "RDF")
|
|
|
|
}
|
|
|
|
|
|
|
|
if root == nil {
|
2014-09-25 12:27:05 +00:00
|
|
|
return &MissingRssNodeError{}
|
2013-10-26 03:26:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
channels := root.SelectNodes(ns, "channel")
|
2009-11-23 12:46:12 +00:00
|
|
|
for _, node := range channels {
|
2013-12-05 13:05:24 +00:00
|
|
|
ch = new(Channel)
|
|
|
|
foundChannels = append(foundChannels, ch)
|
2009-11-23 12:46:12 +00:00
|
|
|
|
2011-05-11 15:40:56 +00:00
|
|
|
ch.Title = node.S(ns, "title")
|
2011-02-01 14:30:39 +00:00
|
|
|
list = node.SelectNodes(ns, "link")
|
2010-05-23 14:21:30 +00:00
|
|
|
ch.Links = make([]Link, len(list))
|
2010-12-17 23:25:16 +00:00
|
|
|
|
2009-11-23 12:46:12 +00:00
|
|
|
for i, v := range list {
|
2014-01-18 17:41:26 +00:00
|
|
|
if v.Name.Space == "http://www.w3.org/2005/Atom" && v.Name.Local == "link" {
|
|
|
|
ch.Links[i].Href = v.As("", "href")
|
|
|
|
ch.Links[i].Rel = v.As("", "rel")
|
|
|
|
ch.Links[i].Type = v.As("", "type")
|
|
|
|
ch.Links[i].HrefLang = v.As("", "hreflang")
|
|
|
|
} else {
|
|
|
|
ch.Links[i].Href = v.GetValue()
|
|
|
|
}
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2011-05-11 15:40:56 +00:00
|
|
|
ch.Description = node.S(ns, "description")
|
|
|
|
ch.Language = node.S(ns, "language")
|
|
|
|
ch.Copyright = node.S(ns, "copyright")
|
|
|
|
ch.ManagingEditor = node.S(ns, "managingEditor")
|
|
|
|
ch.WebMaster = node.S(ns, "webMaster")
|
|
|
|
ch.PubDate = node.S(ns, "pubDate")
|
|
|
|
ch.LastBuildDate = node.S(ns, "lastBuildDate")
|
|
|
|
ch.Docs = node.S(ns, "docs")
|
2010-05-23 14:21:30 +00:00
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
list = node.SelectNodes(ns, "category")
|
2010-12-17 23:25:16 +00:00
|
|
|
ch.Categories = make([]*Category, len(list))
|
2009-11-23 12:46:12 +00:00
|
|
|
for i, v := range list {
|
2010-12-17 23:25:16 +00:00
|
|
|
ch.Categories[i] = new(Category)
|
2011-05-11 15:40:56 +00:00
|
|
|
ch.Categories[i].Domain = v.As(ns, "domain")
|
2013-09-30 05:23:51 +00:00
|
|
|
ch.Categories[i].Text = v.GetValue()
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
if n = node.SelectNode(ns, "generator"); n != nil {
|
2010-05-23 14:21:30 +00:00
|
|
|
ch.Generator = Generator{}
|
2013-09-30 05:23:51 +00:00
|
|
|
ch.Generator.Text = n.GetValue()
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2011-05-11 15:40:56 +00:00
|
|
|
ch.TTL = node.I(ns, "ttl")
|
|
|
|
ch.Rating = node.S(ns, "rating")
|
2009-11-23 12:46:12 +00:00
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
list = node.SelectNodes(ns, "hour")
|
2010-05-23 14:21:30 +00:00
|
|
|
ch.SkipHours = make([]int, len(list))
|
2009-11-23 12:46:12 +00:00
|
|
|
for i, v := range list {
|
2011-05-11 15:40:56 +00:00
|
|
|
ch.SkipHours[i] = v.I(ns, "hour")
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
list = node.SelectNodes(ns, "days")
|
2010-05-23 14:21:30 +00:00
|
|
|
ch.SkipDays = make([]int, len(list))
|
2009-11-23 12:46:12 +00:00
|
|
|
for i, v := range list {
|
2013-09-30 05:23:51 +00:00
|
|
|
ch.SkipDays[i] = days[v.GetValue()]
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
if n = node.SelectNode(ns, "image"); n != nil {
|
2011-05-11 15:40:56 +00:00
|
|
|
ch.Image.Title = n.S(ns, "title")
|
|
|
|
ch.Image.Url = n.S(ns, "url")
|
|
|
|
ch.Image.Link = n.S(ns, "link")
|
|
|
|
ch.Image.Width = n.I(ns, "width")
|
|
|
|
ch.Image.Height = n.I(ns, "height")
|
|
|
|
ch.Image.Description = n.S(ns, "description")
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
if n = node.SelectNode(ns, "cloud"); n != nil {
|
2010-05-23 14:21:30 +00:00
|
|
|
ch.Cloud = Cloud{}
|
2011-05-11 15:40:56 +00:00
|
|
|
ch.Cloud.Domain = n.As(ns, "domain")
|
|
|
|
ch.Cloud.Port = n.Ai(ns, "port")
|
|
|
|
ch.Cloud.Path = n.As(ns, "path")
|
|
|
|
ch.Cloud.RegisterProcedure = n.As(ns, "registerProcedure")
|
|
|
|
ch.Cloud.Protocol = n.As(ns, "protocol")
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
if n = node.SelectNode(ns, "textInput"); n != nil {
|
2010-05-23 14:21:30 +00:00
|
|
|
ch.TextInput = Input{}
|
2011-05-11 15:40:56 +00:00
|
|
|
ch.TextInput.Title = n.S(ns, "title")
|
|
|
|
ch.TextInput.Description = n.S(ns, "description")
|
|
|
|
ch.TextInput.Name = n.S(ns, "name")
|
|
|
|
ch.TextInput.Link = n.S(ns, "link")
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
list = node.SelectNodes(ns, "item")
|
2013-05-10 10:44:35 +00:00
|
|
|
if len(list) == 0 {
|
|
|
|
list = doc.SelectNodes(ns, "item")
|
|
|
|
}
|
2010-12-17 23:25:16 +00:00
|
|
|
|
2009-11-23 12:46:12 +00:00
|
|
|
for _, item := range list {
|
2010-12-17 23:25:16 +00:00
|
|
|
i = new(Item)
|
2011-05-11 15:40:56 +00:00
|
|
|
i.Title = item.S(ns, "title")
|
|
|
|
i.Description = item.S(ns, "description")
|
2009-11-23 12:46:12 +00:00
|
|
|
|
2011-08-26 07:50:14 +00:00
|
|
|
tl = item.SelectNodes(ns, "link")
|
2010-12-17 23:25:16 +00:00
|
|
|
for _, v := range tl {
|
|
|
|
lnk := new(Link)
|
2014-01-18 17:41:26 +00:00
|
|
|
if v.Name.Space == "http://www.w3.org/2005/Atom" && v.Name.Local == "link" {
|
|
|
|
lnk.Href = v.As("", "href")
|
|
|
|
lnk.Rel = v.As("", "rel")
|
|
|
|
lnk.Type = v.As("", "type")
|
|
|
|
lnk.HrefLang = v.As("", "hreflang")
|
|
|
|
} else {
|
|
|
|
lnk.Href = v.GetValue()
|
|
|
|
}
|
|
|
|
|
2010-12-17 20:57:48 +00:00
|
|
|
i.Links = append(i.Links, lnk)
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
if n = item.SelectNode(ns, "author"); n != nil {
|
2013-09-30 05:23:51 +00:00
|
|
|
i.Author.Name = n.GetValue()
|
2013-11-28 09:22:09 +00:00
|
|
|
|
|
|
|
} else if n = item.SelectNode(ns, "creator"); n != nil {
|
|
|
|
i.Author.Name = n.GetValue()
|
2013-07-07 15:49:28 +00:00
|
|
|
}
|
2009-11-23 12:46:12 +00:00
|
|
|
|
2011-05-11 15:40:56 +00:00
|
|
|
i.Comments = item.S(ns, "comments")
|
2013-11-28 09:23:49 +00:00
|
|
|
|
2013-11-28 09:22:09 +00:00
|
|
|
guid := item.S(ns, "guid")
|
|
|
|
if len(guid) > 0 {
|
|
|
|
i.Guid = &guid
|
|
|
|
}
|
|
|
|
|
2011-05-11 15:40:56 +00:00
|
|
|
i.PubDate = item.S(ns, "pubDate")
|
2009-11-23 12:46:12 +00:00
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
tl = item.SelectNodes(ns, "category")
|
2010-12-17 23:25:16 +00:00
|
|
|
for _, lv := range tl {
|
|
|
|
cat := new(Category)
|
2011-05-11 15:40:56 +00:00
|
|
|
cat.Domain = lv.As(ns, "domain")
|
2013-09-30 05:23:51 +00:00
|
|
|
cat.Text = lv.GetValue()
|
2010-12-17 23:25:16 +00:00
|
|
|
i.Categories = append(i.Categories, cat)
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
tl = item.SelectNodes(ns, "enclosure")
|
2010-12-17 23:25:16 +00:00
|
|
|
for _, lv := range tl {
|
|
|
|
enc := new(Enclosure)
|
2011-05-11 15:40:56 +00:00
|
|
|
enc.Url = lv.As(ns, "url")
|
|
|
|
enc.Length = lv.Ai64(ns, "length")
|
|
|
|
enc.Type = lv.As(ns, "type")
|
2010-12-17 23:25:16 +00:00
|
|
|
i.Enclosures = append(i.Enclosures, enc)
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2011-02-01 14:30:39 +00:00
|
|
|
if src := item.SelectNode(ns, "source"); src != nil {
|
2010-12-17 23:25:16 +00:00
|
|
|
i.Source = new(Source)
|
2011-05-11 15:40:56 +00:00
|
|
|
i.Source.Url = src.As(ns, "url")
|
2013-09-30 05:23:51 +00:00
|
|
|
i.Source.Text = src.GetValue()
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
|
|
|
|
2013-05-10 11:55:33 +00:00
|
|
|
tl = item.SelectNodes("http://purl.org/rss/1.0/modules/content/", "*")
|
|
|
|
for _, lv := range tl {
|
|
|
|
if lv.Name.Local == "encoded" {
|
|
|
|
i.Content = new(Content)
|
|
|
|
i.Content.Text = lv.String()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-23 16:57:26 +00:00
|
|
|
i.Extensions = make(map[string]map[string][]Extension)
|
2014-11-22 22:35:38 +00:00
|
|
|
for _, lv := range item.Children {
|
2014-01-23 19:37:18 +00:00
|
|
|
getExtensions(&i.Extensions, lv)
|
2014-01-18 14:30:56 +00:00
|
|
|
}
|
|
|
|
|
2010-12-17 20:57:48 +00:00
|
|
|
ch.Items = append(ch.Items, i)
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
2014-01-23 19:37:50 +00:00
|
|
|
|
|
|
|
ch.Extensions = make(map[string]map[string][]Extension)
|
2014-11-22 22:35:38 +00:00
|
|
|
for _, v := range node.Children {
|
2014-01-23 19:37:50 +00:00
|
|
|
if v.Name.Space != "" {
|
|
|
|
getExtensions(&ch.Extensions, v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-23 12:46:12 +00:00
|
|
|
}
|
2013-12-05 13:05:24 +00:00
|
|
|
this.Channels = foundChannels
|
2009-11-23 12:46:12 +00:00
|
|
|
return
|
|
|
|
}
|
2014-01-18 14:30:56 +00:00
|
|
|
|
2014-01-23 19:37:18 +00:00
|
|
|
func getExtensions(extensionsX *map[string]map[string][]Extension, node *xmlx.Node) {
|
|
|
|
extentions := *extensionsX
|
|
|
|
|
2014-01-23 16:57:26 +00:00
|
|
|
if node.Name.Space != "" {
|
2014-01-23 19:37:18 +00:00
|
|
|
extensione, noErrors := getExtension(node)
|
|
|
|
if noErrors {
|
|
|
|
if len(extentions[node.Name.Space]) == 0 {
|
|
|
|
extentions[node.Name.Space] = make(map[string][]Extension, 0)
|
2014-01-23 16:57:26 +00:00
|
|
|
}
|
2014-01-23 19:37:18 +00:00
|
|
|
if len(extentions[node.Name.Space][node.Name.Local]) == 0 {
|
|
|
|
extentions[node.Name.Space][node.Name.Local] = make([]Extension, 0)
|
|
|
|
}
|
|
|
|
extentions[node.Name.Space][node.Name.Local] = append(extentions[node.Name.Space][node.Name.Local], extensione)
|
2014-01-23 16:57:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-23 19:37:18 +00:00
|
|
|
func getExtension(node *xmlx.Node) (Extension, bool) {
|
2014-01-23 16:57:26 +00:00
|
|
|
var extension Extension
|
2014-01-18 14:30:56 +00:00
|
|
|
if node.Name.Space != "" {
|
|
|
|
extension = Extension{Name: node.Name.Local, Value: node.GetValue()}
|
|
|
|
extension.Attrs = make(map[string]string)
|
2014-01-23 16:57:26 +00:00
|
|
|
extension.Childrens = make(map[string][]Extension, 0)
|
2014-01-18 14:30:56 +00:00
|
|
|
for _, x := range node.Attributes {
|
|
|
|
extension.Attrs[x.Name.Local] = x.Value
|
|
|
|
}
|
|
|
|
for _, y := range node.Children {
|
2014-01-23 19:37:18 +00:00
|
|
|
children, ok := getExtension(y)
|
2014-01-23 16:57:26 +00:00
|
|
|
if ok {
|
|
|
|
extension.Childrens[y.Name.Local] = append(extension.Childrens[y.Name.Local], children)
|
2014-01-18 14:30:56 +00:00
|
|
|
}
|
|
|
|
}
|
2014-01-23 16:57:26 +00:00
|
|
|
return extension, true
|
2014-01-18 14:30:56 +00:00
|
|
|
} else {
|
2014-01-23 16:57:26 +00:00
|
|
|
return extension, false
|
2014-01-18 14:30:56 +00:00
|
|
|
}
|
|
|
|
}
|