rss 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +6 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +88 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/rss.rb +92 -0
- data/lib/rss/0.9.rb +462 -0
- data/lib/rss/1.0.rb +485 -0
- data/lib/rss/2.0.rb +143 -0
- data/lib/rss/atom.rb +1025 -0
- data/lib/rss/content.rb +34 -0
- data/lib/rss/content/1.0.rb +10 -0
- data/lib/rss/content/2.0.rb +12 -0
- data/lib/rss/converter.rb +171 -0
- data/lib/rss/dublincore.rb +164 -0
- data/lib/rss/dublincore/1.0.rb +13 -0
- data/lib/rss/dublincore/2.0.rb +13 -0
- data/lib/rss/dublincore/atom.rb +17 -0
- data/lib/rss/image.rb +198 -0
- data/lib/rss/itunes.rb +413 -0
- data/lib/rss/maker.rb +79 -0
- data/lib/rss/maker/0.9.rb +509 -0
- data/lib/rss/maker/1.0.rb +436 -0
- data/lib/rss/maker/2.0.rb +224 -0
- data/lib/rss/maker/atom.rb +173 -0
- data/lib/rss/maker/base.rb +945 -0
- data/lib/rss/maker/content.rb +22 -0
- data/lib/rss/maker/dublincore.rb +122 -0
- data/lib/rss/maker/entry.rb +164 -0
- data/lib/rss/maker/feed.rb +427 -0
- data/lib/rss/maker/image.rb +112 -0
- data/lib/rss/maker/itunes.rb +243 -0
- data/lib/rss/maker/slash.rb +34 -0
- data/lib/rss/maker/syndication.rb +19 -0
- data/lib/rss/maker/taxonomy.rb +119 -0
- data/lib/rss/maker/trackback.rb +62 -0
- data/lib/rss/parser.rb +589 -0
- data/lib/rss/rexmlparser.rb +50 -0
- data/lib/rss/rss.rb +1346 -0
- data/lib/rss/slash.rb +52 -0
- data/lib/rss/syndication.rb +69 -0
- data/lib/rss/taxonomy.rb +148 -0
- data/lib/rss/trackback.rb +291 -0
- data/lib/rss/utils.rb +200 -0
- data/lib/rss/xml-stylesheet.rb +106 -0
- data/lib/rss/xml.rb +72 -0
- data/lib/rss/xmlparser.rb +95 -0
- data/lib/rss/xmlscanner.rb +122 -0
- data/rss.gemspec +38 -0
- metadata +138 -0
data/lib/rss/2.0.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
require "rss/0.9"
|
3
|
+
|
4
|
+
module RSS
|
5
|
+
|
6
|
+
##
|
7
|
+
# = RSS 2.0 support
|
8
|
+
#
|
9
|
+
# RSS has three different versions. This module contains support for version
|
10
|
+
# 2.0[http://www.rssboard.org/rss-specification]
|
11
|
+
#
|
12
|
+
# == Producing RSS 2.0
|
13
|
+
#
|
14
|
+
# Producing our own RSS feeds is easy as well. Let's make a very basic feed:
|
15
|
+
#
|
16
|
+
# require "rss"
|
17
|
+
#
|
18
|
+
# rss = RSS::Maker.make("2.0") do |maker|
|
19
|
+
# maker.channel.language = "en"
|
20
|
+
# maker.channel.author = "matz"
|
21
|
+
# maker.channel.updated = Time.now.to_s
|
22
|
+
# maker.channel.link = "http://www.ruby-lang.org/en/feeds/news.rss"
|
23
|
+
# maker.channel.title = "Example Feed"
|
24
|
+
# maker.channel.description = "A longer description of my feed."
|
25
|
+
# maker.items.new_item do |item|
|
26
|
+
# item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/"
|
27
|
+
# item.title = "Ruby 1.9.2-p136 is released"
|
28
|
+
# item.updated = Time.now.to_s
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# puts rss
|
33
|
+
#
|
34
|
+
# As you can see, this is a very Builder-like DSL. This code will spit out an
|
35
|
+
# RSS 2.0 feed with one item. If we needed a second item, we'd make another
|
36
|
+
# block with maker.items.new_item and build a second one.
|
37
|
+
class Rss
|
38
|
+
|
39
|
+
class Channel
|
40
|
+
|
41
|
+
[
|
42
|
+
["generator"],
|
43
|
+
["ttl", :integer],
|
44
|
+
].each do |name, type|
|
45
|
+
install_text_element(name, "", "?", name, type)
|
46
|
+
end
|
47
|
+
|
48
|
+
[
|
49
|
+
%w(category categories),
|
50
|
+
].each do |name, plural_name|
|
51
|
+
install_have_children_element(name, "", "*", name, plural_name)
|
52
|
+
end
|
53
|
+
|
54
|
+
[
|
55
|
+
["image", "?"],
|
56
|
+
["language", "?"],
|
57
|
+
].each do |name, occurs|
|
58
|
+
install_model(name, "", occurs)
|
59
|
+
end
|
60
|
+
|
61
|
+
Category = Item::Category
|
62
|
+
|
63
|
+
class Item
|
64
|
+
|
65
|
+
[
|
66
|
+
["comments", "?"],
|
67
|
+
["author", "?"],
|
68
|
+
].each do |name, occurs|
|
69
|
+
install_text_element(name, "", occurs)
|
70
|
+
end
|
71
|
+
|
72
|
+
[
|
73
|
+
["pubDate", '?'],
|
74
|
+
].each do |name, occurs|
|
75
|
+
install_date_element(name, "", occurs, name, 'rfc822')
|
76
|
+
end
|
77
|
+
alias date pubDate
|
78
|
+
alias date= pubDate=
|
79
|
+
|
80
|
+
[
|
81
|
+
["guid", '?'],
|
82
|
+
].each do |name, occurs|
|
83
|
+
install_have_child_element(name, "", occurs)
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
alias _setup_maker_element setup_maker_element
|
88
|
+
def setup_maker_element(item)
|
89
|
+
_setup_maker_element(item)
|
90
|
+
@guid.setup_maker(item) if @guid
|
91
|
+
end
|
92
|
+
|
93
|
+
class Guid < Element
|
94
|
+
|
95
|
+
include RSS09
|
96
|
+
|
97
|
+
[
|
98
|
+
["isPermaLink", "", false, :boolean]
|
99
|
+
].each do |name, uri, required, type|
|
100
|
+
install_get_attribute(name, uri, required, type)
|
101
|
+
end
|
102
|
+
|
103
|
+
content_setup
|
104
|
+
|
105
|
+
def initialize(*args)
|
106
|
+
if Utils.element_initialize_arguments?(args)
|
107
|
+
super
|
108
|
+
else
|
109
|
+
super()
|
110
|
+
self.isPermaLink = args[0]
|
111
|
+
self.content = args[1]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
alias_method :_PermaLink?, :PermaLink?
|
116
|
+
private :_PermaLink?
|
117
|
+
def PermaLink?
|
118
|
+
perma = _PermaLink?
|
119
|
+
perma or perma.nil?
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
def maker_target(item)
|
124
|
+
item.guid
|
125
|
+
end
|
126
|
+
|
127
|
+
def setup_maker_attributes(guid)
|
128
|
+
guid.isPermaLink = isPermaLink
|
129
|
+
guid.content = content
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
RSS09::ELEMENTS.each do |name|
|
140
|
+
BaseListener.install_get_text_element("", name, name)
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
data/lib/rss/atom.rb
ADDED
@@ -0,0 +1,1025 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
require_relative 'parser'
|
3
|
+
|
4
|
+
module RSS
|
5
|
+
##
|
6
|
+
# Atom is an XML-based document format that is used to describe 'feeds' of related information.
|
7
|
+
# A typical use is in a news feed where the information is periodically updated and which users
|
8
|
+
# can subscribe to. The Atom format is described in http://tools.ietf.org/html/rfc4287
|
9
|
+
#
|
10
|
+
# The Atom module provides support in reading and creating feeds.
|
11
|
+
#
|
12
|
+
# See the RSS module for examples consuming and creating feeds.
|
13
|
+
module Atom
|
14
|
+
|
15
|
+
##
|
16
|
+
# The Atom URI W3C Namespace
|
17
|
+
|
18
|
+
URI = "http://www.w3.org/2005/Atom"
|
19
|
+
|
20
|
+
##
|
21
|
+
# The XHTML URI W3C Namespace
|
22
|
+
|
23
|
+
XHTML_URI = "http://www.w3.org/1999/xhtml"
|
24
|
+
|
25
|
+
module CommonModel
|
26
|
+
NSPOOL = {}
|
27
|
+
ELEMENTS = []
|
28
|
+
|
29
|
+
def self.append_features(klass)
|
30
|
+
super
|
31
|
+
klass.install_must_call_validator("atom", URI)
|
32
|
+
[
|
33
|
+
["lang", :xml],
|
34
|
+
["base", :xml],
|
35
|
+
].each do |name, uri, required|
|
36
|
+
klass.install_get_attribute(name, uri, required, [nil, :inherit])
|
37
|
+
end
|
38
|
+
klass.class_eval do
|
39
|
+
class << self
|
40
|
+
# Returns the Atom URI W3C Namespace
|
41
|
+
def required_uri
|
42
|
+
URI
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns true
|
46
|
+
def need_parent?
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
module ContentModel
|
55
|
+
module ClassMethods
|
56
|
+
def content_type
|
57
|
+
@content_type ||= nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class << self
|
62
|
+
def append_features(klass)
|
63
|
+
super
|
64
|
+
klass.extend(ClassMethods)
|
65
|
+
klass.content_setup(klass.content_type, klass.tag_name)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def maker_target(target)
|
70
|
+
target
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def setup_maker_element_writer
|
75
|
+
"#{self.class.name.split(/::/).last.downcase}="
|
76
|
+
end
|
77
|
+
|
78
|
+
def setup_maker_element(target)
|
79
|
+
target.__send__(setup_maker_element_writer, content)
|
80
|
+
super
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
module URIContentModel
|
85
|
+
class << self
|
86
|
+
def append_features(klass)
|
87
|
+
super
|
88
|
+
klass.class_eval do
|
89
|
+
@content_type = [nil, :uri]
|
90
|
+
include(ContentModel)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# The TextConstruct module is used to define a Text construct Atom element,
|
97
|
+
# which is used to store small quantities of human-readable text.
|
98
|
+
#
|
99
|
+
# The TextConstruct has a type attribute, e.g. text, html, xhtml
|
100
|
+
#
|
101
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#text.constructs
|
102
|
+
module TextConstruct
|
103
|
+
def self.append_features(klass)
|
104
|
+
super
|
105
|
+
klass.class_eval do
|
106
|
+
[
|
107
|
+
["type", ""],
|
108
|
+
].each do |name, uri, required|
|
109
|
+
install_get_attribute(name, uri, required, :text_type)
|
110
|
+
end
|
111
|
+
|
112
|
+
content_setup
|
113
|
+
add_need_initialize_variable("xhtml")
|
114
|
+
|
115
|
+
class << self
|
116
|
+
def xml_getter
|
117
|
+
"xhtml"
|
118
|
+
end
|
119
|
+
|
120
|
+
def xml_setter
|
121
|
+
"xhtml="
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
attr_writer :xhtml
|
128
|
+
|
129
|
+
# Returns or builds the XHTML content.
|
130
|
+
def xhtml
|
131
|
+
return @xhtml if @xhtml.nil?
|
132
|
+
if @xhtml.is_a?(XML::Element) and
|
133
|
+
[@xhtml.name, @xhtml.uri] == ["div", XHTML_URI]
|
134
|
+
return @xhtml
|
135
|
+
end
|
136
|
+
|
137
|
+
children = @xhtml
|
138
|
+
children = [children] unless children.is_a?(Array)
|
139
|
+
XML::Element.new("div", nil, XHTML_URI,
|
140
|
+
{"xmlns" => XHTML_URI}, children)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Returns true if type is "xhtml".
|
144
|
+
def have_xml_content?
|
145
|
+
@type == "xhtml"
|
146
|
+
end
|
147
|
+
|
148
|
+
# Raises a MissingTagError or NotExpectedTagError
|
149
|
+
# if the element is not properly formatted.
|
150
|
+
def atom_validate(ignore_unknown_element, tags, uri)
|
151
|
+
if have_xml_content?
|
152
|
+
if @xhtml.nil?
|
153
|
+
raise MissingTagError.new("div", tag_name)
|
154
|
+
end
|
155
|
+
unless [@xhtml.name, @xhtml.uri] == ["div", XHTML_URI]
|
156
|
+
raise NotExpectedTagError.new(@xhtml.name, @xhtml.uri, tag_name)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
def maker_target(target)
|
163
|
+
target.__send__(self.class.name.split(/::/).last.downcase) {|x| x}
|
164
|
+
end
|
165
|
+
|
166
|
+
def setup_maker_attributes(target)
|
167
|
+
target.type = type
|
168
|
+
target.content = content
|
169
|
+
target.xml_content = @xhtml
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# The PersonConstruct module is used to define a person Atom element that can be
|
174
|
+
# used to describe a person, corporation or similar entity.
|
175
|
+
#
|
176
|
+
# The PersonConstruct has a Name, Uri and Email child elements.
|
177
|
+
#
|
178
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#atomPersonConstruct
|
179
|
+
module PersonConstruct
|
180
|
+
|
181
|
+
# Adds attributes for name, uri, and email to the +klass+
|
182
|
+
def self.append_features(klass)
|
183
|
+
super
|
184
|
+
klass.class_eval do
|
185
|
+
[
|
186
|
+
["name", nil],
|
187
|
+
["uri", "?"],
|
188
|
+
["email", "?"],
|
189
|
+
].each do |tag, occurs|
|
190
|
+
install_have_attribute_element(tag, URI, occurs, nil, :content)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def maker_target(target)
|
196
|
+
target.__send__("new_#{self.class.name.split(/::/).last.downcase}")
|
197
|
+
end
|
198
|
+
|
199
|
+
# The name of the person or entity.
|
200
|
+
#
|
201
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.name
|
202
|
+
class Name < RSS::Element
|
203
|
+
include CommonModel
|
204
|
+
include ContentModel
|
205
|
+
end
|
206
|
+
|
207
|
+
# The URI of the person or entity.
|
208
|
+
#
|
209
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.uri
|
210
|
+
class Uri < RSS::Element
|
211
|
+
include CommonModel
|
212
|
+
include URIContentModel
|
213
|
+
end
|
214
|
+
|
215
|
+
# The email of the person or entity.
|
216
|
+
#
|
217
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.email
|
218
|
+
class Email < RSS::Element
|
219
|
+
include CommonModel
|
220
|
+
include ContentModel
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# Element used to describe an Atom date and time in the ISO 8601 format
|
225
|
+
#
|
226
|
+
# Examples:
|
227
|
+
# * 2013-03-04T15:30:02Z
|
228
|
+
# * 2013-03-04T10:30:02-05:00
|
229
|
+
module DateConstruct
|
230
|
+
def self.append_features(klass)
|
231
|
+
super
|
232
|
+
klass.class_eval do
|
233
|
+
@content_type = :w3cdtf
|
234
|
+
include(ContentModel)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# Raises NotAvailableValueError if element content is nil
|
239
|
+
def atom_validate(ignore_unknown_element, tags, uri)
|
240
|
+
raise NotAvailableValueError.new(tag_name, "") if content.nil?
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
module DuplicateLinkChecker
|
245
|
+
# Checks if there are duplicate links with the same type and hreflang attributes
|
246
|
+
# that have an alternate (or empty) rel attribute
|
247
|
+
#
|
248
|
+
# Raises a TooMuchTagError if there are duplicates found
|
249
|
+
def validate_duplicate_links(links)
|
250
|
+
link_infos = {}
|
251
|
+
links.each do |link|
|
252
|
+
rel = link.rel || "alternate"
|
253
|
+
next unless rel == "alternate"
|
254
|
+
key = [link.hreflang, link.type]
|
255
|
+
if link_infos.has_key?(key)
|
256
|
+
raise TooMuchTagError.new("link", tag_name)
|
257
|
+
end
|
258
|
+
link_infos[key] = true
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# Defines the top-level element of an Atom Feed Document.
|
264
|
+
# It consists of a number of children Entry elements,
|
265
|
+
# and has the following attributes:
|
266
|
+
#
|
267
|
+
# * author
|
268
|
+
# * categories
|
269
|
+
# * category
|
270
|
+
# * content
|
271
|
+
# * contributor
|
272
|
+
# * entries (aliased as items)
|
273
|
+
# * entry
|
274
|
+
# * generator
|
275
|
+
# * icon
|
276
|
+
# * id
|
277
|
+
# * link
|
278
|
+
# * logo
|
279
|
+
# * rights
|
280
|
+
# * subtitle
|
281
|
+
# * title
|
282
|
+
# * updated
|
283
|
+
#
|
284
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.feed
|
285
|
+
class Feed < RSS::Element
|
286
|
+
include RootElementMixin
|
287
|
+
include CommonModel
|
288
|
+
include DuplicateLinkChecker
|
289
|
+
|
290
|
+
install_ns('', URI)
|
291
|
+
|
292
|
+
[
|
293
|
+
["author", "*", :children],
|
294
|
+
["category", "*", :children, "categories"],
|
295
|
+
["contributor", "*", :children],
|
296
|
+
["generator", "?"],
|
297
|
+
["icon", "?", nil, :content],
|
298
|
+
["id", nil, nil, :content],
|
299
|
+
["link", "*", :children],
|
300
|
+
["logo", "?"],
|
301
|
+
["rights", "?"],
|
302
|
+
["subtitle", "?", nil, :content],
|
303
|
+
["title", nil, nil, :content],
|
304
|
+
["updated", nil, nil, :content],
|
305
|
+
["entry", "*", :children, "entries"],
|
306
|
+
].each do |tag, occurs, type, *args|
|
307
|
+
type ||= :child
|
308
|
+
__send__("install_have_#{type}_element",
|
309
|
+
tag, URI, occurs, tag, *args)
|
310
|
+
end
|
311
|
+
|
312
|
+
# Creates a new Atom feed
|
313
|
+
def initialize(version=nil, encoding=nil, standalone=nil)
|
314
|
+
super("1.0", version, encoding, standalone)
|
315
|
+
@feed_type = "atom"
|
316
|
+
@feed_subtype = "feed"
|
317
|
+
end
|
318
|
+
|
319
|
+
alias_method :items, :entries
|
320
|
+
|
321
|
+
# Returns true if there are any authors for the feed or any of the Entry
|
322
|
+
# child elements have an author
|
323
|
+
def have_author?
|
324
|
+
authors.any? {|author| !author.to_s.empty?} or
|
325
|
+
entries.any? {|entry| entry.have_author?(false)}
|
326
|
+
end
|
327
|
+
|
328
|
+
private
|
329
|
+
def atom_validate(ignore_unknown_element, tags, uri)
|
330
|
+
unless have_author?
|
331
|
+
raise MissingTagError.new("author", tag_name)
|
332
|
+
end
|
333
|
+
validate_duplicate_links(links)
|
334
|
+
end
|
335
|
+
|
336
|
+
def have_required_elements?
|
337
|
+
super and have_author?
|
338
|
+
end
|
339
|
+
|
340
|
+
def maker_target(maker)
|
341
|
+
maker.channel
|
342
|
+
end
|
343
|
+
|
344
|
+
def setup_maker_element(channel)
|
345
|
+
prev_dc_dates = channel.dc_dates.to_a.dup
|
346
|
+
super
|
347
|
+
channel.about = id.content if id
|
348
|
+
channel.dc_dates.replace(prev_dc_dates)
|
349
|
+
end
|
350
|
+
|
351
|
+
def setup_maker_elements(channel)
|
352
|
+
super
|
353
|
+
items = channel.maker.items
|
354
|
+
entries.each do |entry|
|
355
|
+
entry.setup_maker(items)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
# PersonConstruct that contains information regarding the author
|
360
|
+
# of a Feed or Entry.
|
361
|
+
#
|
362
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.author
|
363
|
+
class Author < RSS::Element
|
364
|
+
include CommonModel
|
365
|
+
include PersonConstruct
|
366
|
+
end
|
367
|
+
|
368
|
+
# Contains information about a category associated with a Feed or Entry.
|
369
|
+
# It has the following attributes:
|
370
|
+
#
|
371
|
+
# * term
|
372
|
+
# * scheme
|
373
|
+
# * label
|
374
|
+
#
|
375
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.category
|
376
|
+
class Category < RSS::Element
|
377
|
+
include CommonModel
|
378
|
+
|
379
|
+
[
|
380
|
+
["term", "", true],
|
381
|
+
["scheme", "", false, [nil, :uri]],
|
382
|
+
["label", ""],
|
383
|
+
].each do |name, uri, required, type|
|
384
|
+
install_get_attribute(name, uri, required, type)
|
385
|
+
end
|
386
|
+
|
387
|
+
private
|
388
|
+
def maker_target(target)
|
389
|
+
target.new_category
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
# PersonConstruct that contains information regarding the
|
394
|
+
# contributors of a Feed or Entry.
|
395
|
+
#
|
396
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.contributor
|
397
|
+
class Contributor < RSS::Element
|
398
|
+
include CommonModel
|
399
|
+
include PersonConstruct
|
400
|
+
end
|
401
|
+
|
402
|
+
# Contains information on the agent used to generate the feed.
|
403
|
+
#
|
404
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.generator
|
405
|
+
class Generator < RSS::Element
|
406
|
+
include CommonModel
|
407
|
+
include ContentModel
|
408
|
+
|
409
|
+
[
|
410
|
+
["uri", "", false, [nil, :uri]],
|
411
|
+
["version", ""],
|
412
|
+
].each do |name, uri, required, type|
|
413
|
+
install_get_attribute(name, uri, required, type)
|
414
|
+
end
|
415
|
+
|
416
|
+
private
|
417
|
+
def setup_maker_attributes(target)
|
418
|
+
target.generator do |generator|
|
419
|
+
generator.uri = uri if uri
|
420
|
+
generator.version = version if version
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
# Defines an image that provides a visual identification for a eed.
|
426
|
+
# The image should have an aspect ratio of 1:1.
|
427
|
+
#
|
428
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.icon
|
429
|
+
class Icon < RSS::Element
|
430
|
+
include CommonModel
|
431
|
+
include URIContentModel
|
432
|
+
end
|
433
|
+
|
434
|
+
# Defines the Universally Unique Identifier (UUID) for a Feed or Entry.
|
435
|
+
#
|
436
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.id
|
437
|
+
class Id < RSS::Element
|
438
|
+
include CommonModel
|
439
|
+
include URIContentModel
|
440
|
+
end
|
441
|
+
|
442
|
+
# Defines a reference to a Web resource. It has the following
|
443
|
+
# attributes:
|
444
|
+
#
|
445
|
+
# * href
|
446
|
+
# * rel
|
447
|
+
# * type
|
448
|
+
# * hreflang
|
449
|
+
# * title
|
450
|
+
# * length
|
451
|
+
#
|
452
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.link
|
453
|
+
class Link < RSS::Element
|
454
|
+
include CommonModel
|
455
|
+
|
456
|
+
[
|
457
|
+
["href", "", true, [nil, :uri]],
|
458
|
+
["rel", ""],
|
459
|
+
["type", ""],
|
460
|
+
["hreflang", ""],
|
461
|
+
["title", ""],
|
462
|
+
["length", ""],
|
463
|
+
].each do |name, uri, required, type|
|
464
|
+
install_get_attribute(name, uri, required, type)
|
465
|
+
end
|
466
|
+
|
467
|
+
private
|
468
|
+
def maker_target(target)
|
469
|
+
target.new_link
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
# Defines an image that provides a visual identification for the Feed.
|
474
|
+
# The image should have an aspect ratio of 2:1 (horizontal:vertical).
|
475
|
+
#
|
476
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.logo
|
477
|
+
class Logo < RSS::Element
|
478
|
+
include CommonModel
|
479
|
+
include URIContentModel
|
480
|
+
|
481
|
+
def maker_target(target)
|
482
|
+
target.maker.image
|
483
|
+
end
|
484
|
+
|
485
|
+
private
|
486
|
+
def setup_maker_element_writer
|
487
|
+
"url="
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
# TextConstruct that contains copyright information regarding
|
492
|
+
# the content in an Entry or Feed. It should not be used to
|
493
|
+
# convey machine readable licensing information.
|
494
|
+
#
|
495
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.rights
|
496
|
+
class Rights < RSS::Element
|
497
|
+
include CommonModel
|
498
|
+
include TextConstruct
|
499
|
+
end
|
500
|
+
|
501
|
+
# TextConstruct that conveys a description or subtitle for a Feed.
|
502
|
+
#
|
503
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.subtitle
|
504
|
+
class Subtitle < RSS::Element
|
505
|
+
include CommonModel
|
506
|
+
include TextConstruct
|
507
|
+
end
|
508
|
+
|
509
|
+
# TextConstruct that conveys a description or title for a Feed or Entry.
|
510
|
+
#
|
511
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.title
|
512
|
+
class Title < RSS::Element
|
513
|
+
include CommonModel
|
514
|
+
include TextConstruct
|
515
|
+
end
|
516
|
+
|
517
|
+
# DateConstruct indicating the most recent time when a Feed or
|
518
|
+
# Entry was modified in a way the publisher considers
|
519
|
+
# significant.
|
520
|
+
#
|
521
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.updated
|
522
|
+
class Updated < RSS::Element
|
523
|
+
include CommonModel
|
524
|
+
include DateConstruct
|
525
|
+
end
|
526
|
+
|
527
|
+
# Defines a child Atom Entry element of an Atom Feed element.
|
528
|
+
# It has the following attributes:
|
529
|
+
#
|
530
|
+
# * author
|
531
|
+
# * category
|
532
|
+
# * categories
|
533
|
+
# * content
|
534
|
+
# * contributor
|
535
|
+
# * id
|
536
|
+
# * link
|
537
|
+
# * published
|
538
|
+
# * rights
|
539
|
+
# * source
|
540
|
+
# * summary
|
541
|
+
# * title
|
542
|
+
# * updated
|
543
|
+
#
|
544
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.entry
|
545
|
+
class Entry < RSS::Element
|
546
|
+
include CommonModel
|
547
|
+
include DuplicateLinkChecker
|
548
|
+
|
549
|
+
[
|
550
|
+
["author", "*", :children],
|
551
|
+
["category", "*", :children, "categories"],
|
552
|
+
["content", "?", :child],
|
553
|
+
["contributor", "*", :children],
|
554
|
+
["id", nil, nil, :content],
|
555
|
+
["link", "*", :children],
|
556
|
+
["published", "?", :child, :content],
|
557
|
+
["rights", "?", :child],
|
558
|
+
["source", "?"],
|
559
|
+
["summary", "?", :child],
|
560
|
+
["title", nil],
|
561
|
+
["updated", nil, :child, :content],
|
562
|
+
].each do |tag, occurs, type, *args|
|
563
|
+
type ||= :attribute
|
564
|
+
__send__("install_have_#{type}_element",
|
565
|
+
tag, URI, occurs, tag, *args)
|
566
|
+
end
|
567
|
+
|
568
|
+
# Returns whether any of the following are true:
|
569
|
+
#
|
570
|
+
# * There are any authors in the feed
|
571
|
+
# * If the parent element has an author and the +check_parent+
|
572
|
+
# parameter was given.
|
573
|
+
# * There is a source element that has an author
|
574
|
+
def have_author?(check_parent=true)
|
575
|
+
authors.any? {|author| !author.to_s.empty?} or
|
576
|
+
(check_parent and @parent and @parent.have_author?) or
|
577
|
+
(source and source.have_author?)
|
578
|
+
end
|
579
|
+
|
580
|
+
private
|
581
|
+
def atom_validate(ignore_unknown_element, tags, uri)
|
582
|
+
unless have_author?
|
583
|
+
raise MissingTagError.new("author", tag_name)
|
584
|
+
end
|
585
|
+
validate_duplicate_links(links)
|
586
|
+
end
|
587
|
+
|
588
|
+
def have_required_elements?
|
589
|
+
super and have_author?
|
590
|
+
end
|
591
|
+
|
592
|
+
def maker_target(items)
|
593
|
+
if items.respond_to?("items")
|
594
|
+
# For backward compatibility
|
595
|
+
items = items.items
|
596
|
+
end
|
597
|
+
items.new_item
|
598
|
+
end
|
599
|
+
|
600
|
+
# Feed::Author
|
601
|
+
Author = Feed::Author
|
602
|
+
# Feed::Category
|
603
|
+
Category = Feed::Category
|
604
|
+
|
605
|
+
# Contains or links to the content of the Entry.
|
606
|
+
# It has the following attributes:
|
607
|
+
#
|
608
|
+
# * type
|
609
|
+
# * src
|
610
|
+
#
|
611
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.content
|
612
|
+
class Content < RSS::Element
|
613
|
+
include CommonModel
|
614
|
+
|
615
|
+
class << self
|
616
|
+
def xml_setter
|
617
|
+
"xml="
|
618
|
+
end
|
619
|
+
|
620
|
+
def xml_getter
|
621
|
+
"xml"
|
622
|
+
end
|
623
|
+
end
|
624
|
+
|
625
|
+
[
|
626
|
+
["type", ""],
|
627
|
+
["src", "", false, [nil, :uri]],
|
628
|
+
].each do |name, uri, required, type|
|
629
|
+
install_get_attribute(name, uri, required, type)
|
630
|
+
end
|
631
|
+
|
632
|
+
content_setup
|
633
|
+
add_need_initialize_variable("xml")
|
634
|
+
|
635
|
+
# Returns the element content in XML.
|
636
|
+
attr_writer :xml
|
637
|
+
|
638
|
+
# Returns true if the element has inline XML content.
|
639
|
+
def have_xml_content?
|
640
|
+
inline_xhtml? or inline_other_xml?
|
641
|
+
end
|
642
|
+
|
643
|
+
# Returns or builds the element content in XML.
|
644
|
+
def xml
|
645
|
+
return @xml unless inline_xhtml?
|
646
|
+
return @xml if @xml.nil?
|
647
|
+
if @xml.is_a?(XML::Element) and
|
648
|
+
[@xml.name, @xml.uri] == ["div", XHTML_URI]
|
649
|
+
return @xml
|
650
|
+
end
|
651
|
+
|
652
|
+
children = @xml
|
653
|
+
children = [children] unless children.is_a?(Array)
|
654
|
+
XML::Element.new("div", nil, XHTML_URI,
|
655
|
+
{"xmlns" => XHTML_URI}, children)
|
656
|
+
end
|
657
|
+
|
658
|
+
# Returns the element content in XHTML.
|
659
|
+
def xhtml
|
660
|
+
if inline_xhtml?
|
661
|
+
xml
|
662
|
+
else
|
663
|
+
nil
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
# Raises a MissingAttributeError, NotAvailableValueError,
|
668
|
+
# MissingTagError or NotExpectedTagError if the element is
|
669
|
+
# not properly formatted.
|
670
|
+
def atom_validate(ignore_unknown_element, tags, uri)
|
671
|
+
if out_of_line?
|
672
|
+
raise MissingAttributeError.new(tag_name, "type") if @type.nil?
|
673
|
+
unless (content.nil? or content.empty?)
|
674
|
+
raise NotAvailableValueError.new(tag_name, content)
|
675
|
+
end
|
676
|
+
elsif inline_xhtml?
|
677
|
+
if @xml.nil?
|
678
|
+
raise MissingTagError.new("div", tag_name)
|
679
|
+
end
|
680
|
+
unless @xml.name == "div" and @xml.uri == XHTML_URI
|
681
|
+
raise NotExpectedTagError.new(@xml.name, @xml.uri, tag_name)
|
682
|
+
end
|
683
|
+
end
|
684
|
+
end
|
685
|
+
|
686
|
+
# Returns true if the element contains inline content
|
687
|
+
# that has a text or HTML media type, or no media type at all.
|
688
|
+
def inline_text?
|
689
|
+
!out_of_line? and [nil, "text", "html"].include?(@type)
|
690
|
+
end
|
691
|
+
|
692
|
+
# Returns true if the element contains inline content that
|
693
|
+
# has a HTML media type.
|
694
|
+
def inline_html?
|
695
|
+
return false if out_of_line?
|
696
|
+
@type == "html" or mime_split == ["text", "html"]
|
697
|
+
end
|
698
|
+
|
699
|
+
# Returns true if the element contains inline content that
|
700
|
+
# has a XHTML media type.
|
701
|
+
def inline_xhtml?
|
702
|
+
!out_of_line? and @type == "xhtml"
|
703
|
+
end
|
704
|
+
|
705
|
+
# Returns true if the element contains inline content that
|
706
|
+
# has a MIME media type.
|
707
|
+
def inline_other?
|
708
|
+
return false if out_of_line?
|
709
|
+
media_type, subtype = mime_split
|
710
|
+
return false if media_type.nil? or subtype.nil?
|
711
|
+
true
|
712
|
+
end
|
713
|
+
|
714
|
+
# Returns true if the element contains inline content that
|
715
|
+
# has a text media type.
|
716
|
+
def inline_other_text?
|
717
|
+
return false unless inline_other?
|
718
|
+
return false if inline_other_xml?
|
719
|
+
|
720
|
+
media_type, = mime_split
|
721
|
+
return true if "text" == media_type.downcase
|
722
|
+
false
|
723
|
+
end
|
724
|
+
|
725
|
+
# Returns true if the element contains inline content that
|
726
|
+
# has a XML media type.
|
727
|
+
def inline_other_xml?
|
728
|
+
return false unless inline_other?
|
729
|
+
|
730
|
+
media_type, subtype = mime_split
|
731
|
+
normalized_mime_type = "#{media_type}/#{subtype}".downcase
|
732
|
+
if /(?:\+xml|^xml)$/ =~ subtype or
|
733
|
+
%w(text/xml-external-parsed-entity
|
734
|
+
application/xml-external-parsed-entity
|
735
|
+
application/xml-dtd).find {|x| x == normalized_mime_type}
|
736
|
+
return true
|
737
|
+
end
|
738
|
+
false
|
739
|
+
end
|
740
|
+
|
741
|
+
# Returns true if the element contains inline content
|
742
|
+
# encoded in base64.
|
743
|
+
def inline_other_base64?
|
744
|
+
inline_other? and !inline_other_text? and !inline_other_xml?
|
745
|
+
end
|
746
|
+
|
747
|
+
# Returns true if the element contains linked content.
|
748
|
+
def out_of_line?
|
749
|
+
not @src.nil?
|
750
|
+
end
|
751
|
+
|
752
|
+
# Splits the type attribute into an array, e.g. ["text", "xml"]
|
753
|
+
def mime_split
|
754
|
+
media_type = subtype = nil
|
755
|
+
if /\A\s*([a-z]+)\/([a-z\+]+)\s*(?:;.*)?\z/i =~ @type.to_s
|
756
|
+
media_type = $1.downcase
|
757
|
+
subtype = $2.downcase
|
758
|
+
end
|
759
|
+
[media_type, subtype]
|
760
|
+
end
|
761
|
+
|
762
|
+
# Returns true if the content needs to be encoded in base64.
|
763
|
+
def need_base64_encode?
|
764
|
+
inline_other_base64?
|
765
|
+
end
|
766
|
+
|
767
|
+
private
|
768
|
+
def empty_content?
|
769
|
+
out_of_line? or super
|
770
|
+
end
|
771
|
+
end
|
772
|
+
|
773
|
+
# Feed::Contributor
|
774
|
+
Contributor = Feed::Contributor
|
775
|
+
# Feed::Id
|
776
|
+
Id = Feed::Id
|
777
|
+
# Feed::Link
|
778
|
+
Link = Feed::Link
|
779
|
+
|
780
|
+
# DateConstruct that usually indicates the time of the initial
|
781
|
+
# creation of an Entry.
|
782
|
+
#
|
783
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.published
|
784
|
+
class Published < RSS::Element
|
785
|
+
include CommonModel
|
786
|
+
include DateConstruct
|
787
|
+
end
|
788
|
+
|
789
|
+
# Feed::Rights
|
790
|
+
Rights = Feed::Rights
|
791
|
+
|
792
|
+
# Defines a Atom Source element. It has the following attributes:
|
793
|
+
#
|
794
|
+
# * author
|
795
|
+
# * category
|
796
|
+
# * categories
|
797
|
+
# * content
|
798
|
+
# * contributor
|
799
|
+
# * generator
|
800
|
+
# * icon
|
801
|
+
# * id
|
802
|
+
# * link
|
803
|
+
# * logo
|
804
|
+
# * rights
|
805
|
+
# * subtitle
|
806
|
+
# * title
|
807
|
+
# * updated
|
808
|
+
#
|
809
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.source
|
810
|
+
class Source < RSS::Element
|
811
|
+
include CommonModel
|
812
|
+
|
813
|
+
[
|
814
|
+
["author", "*", :children],
|
815
|
+
["category", "*", :children, "categories"],
|
816
|
+
["contributor", "*", :children],
|
817
|
+
["generator", "?"],
|
818
|
+
["icon", "?"],
|
819
|
+
["id", "?", nil, :content],
|
820
|
+
["link", "*", :children],
|
821
|
+
["logo", "?"],
|
822
|
+
["rights", "?"],
|
823
|
+
["subtitle", "?"],
|
824
|
+
["title", "?"],
|
825
|
+
["updated", "?", nil, :content],
|
826
|
+
].each do |tag, occurs, type, *args|
|
827
|
+
type ||= :attribute
|
828
|
+
__send__("install_have_#{type}_element",
|
829
|
+
tag, URI, occurs, tag, *args)
|
830
|
+
end
|
831
|
+
|
832
|
+
# Returns true if the Source element has an author.
|
833
|
+
def have_author?
|
834
|
+
!author.to_s.empty?
|
835
|
+
end
|
836
|
+
|
837
|
+
# Feed::Author
|
838
|
+
Author = Feed::Author
|
839
|
+
# Feed::Category
|
840
|
+
Category = Feed::Category
|
841
|
+
# Feed::Contributor
|
842
|
+
Contributor = Feed::Contributor
|
843
|
+
# Feed::Generator
|
844
|
+
Generator = Feed::Generator
|
845
|
+
# Feed::Icon
|
846
|
+
Icon = Feed::Icon
|
847
|
+
# Feed::Id
|
848
|
+
Id = Feed::Id
|
849
|
+
# Feed::Link
|
850
|
+
Link = Feed::Link
|
851
|
+
# Feed::Logo
|
852
|
+
Logo = Feed::Logo
|
853
|
+
# Feed::Rights
|
854
|
+
Rights = Feed::Rights
|
855
|
+
# Feed::Subtitle
|
856
|
+
Subtitle = Feed::Subtitle
|
857
|
+
# Feed::Title
|
858
|
+
Title = Feed::Title
|
859
|
+
# Feed::Updated
|
860
|
+
Updated = Feed::Updated
|
861
|
+
end
|
862
|
+
|
863
|
+
# TextConstruct that describes a summary of the Entry.
|
864
|
+
#
|
865
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.summary
|
866
|
+
class Summary < RSS::Element
|
867
|
+
include CommonModel
|
868
|
+
include TextConstruct
|
869
|
+
end
|
870
|
+
|
871
|
+
# Feed::Title
|
872
|
+
Title = Feed::Title
|
873
|
+
# Feed::Updated
|
874
|
+
Updated = Feed::Updated
|
875
|
+
end
|
876
|
+
end
|
877
|
+
|
878
|
+
# Defines a top-level Atom Entry element,
|
879
|
+
# used as the document element of a stand-alone Atom Entry Document.
|
880
|
+
# It has the following attributes:
|
881
|
+
#
|
882
|
+
# * author
|
883
|
+
# * category
|
884
|
+
# * categories
|
885
|
+
# * content
|
886
|
+
# * contributor
|
887
|
+
# * id
|
888
|
+
# * link
|
889
|
+
# * published
|
890
|
+
# * rights
|
891
|
+
# * source
|
892
|
+
# * summary
|
893
|
+
# * title
|
894
|
+
# * updated
|
895
|
+
#
|
896
|
+
# Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.entry]
|
897
|
+
class Entry < RSS::Element
|
898
|
+
include RootElementMixin
|
899
|
+
include CommonModel
|
900
|
+
include DuplicateLinkChecker
|
901
|
+
|
902
|
+
[
|
903
|
+
["author", "*", :children],
|
904
|
+
["category", "*", :children, "categories"],
|
905
|
+
["content", "?"],
|
906
|
+
["contributor", "*", :children],
|
907
|
+
["id", nil, nil, :content],
|
908
|
+
["link", "*", :children],
|
909
|
+
["published", "?", :child, :content],
|
910
|
+
["rights", "?"],
|
911
|
+
["source", "?"],
|
912
|
+
["summary", "?"],
|
913
|
+
["title", nil],
|
914
|
+
["updated", nil, nil, :content],
|
915
|
+
].each do |tag, occurs, type, *args|
|
916
|
+
type ||= :attribute
|
917
|
+
__send__("install_have_#{type}_element",
|
918
|
+
tag, URI, occurs, tag, *args)
|
919
|
+
end
|
920
|
+
|
921
|
+
# Creates a new Atom Entry element.
|
922
|
+
def initialize(version=nil, encoding=nil, standalone=nil)
|
923
|
+
super("1.0", version, encoding, standalone)
|
924
|
+
@feed_type = "atom"
|
925
|
+
@feed_subtype = "entry"
|
926
|
+
end
|
927
|
+
|
928
|
+
# Returns the Entry in an array.
|
929
|
+
def items
|
930
|
+
[self]
|
931
|
+
end
|
932
|
+
|
933
|
+
# Sets up the +maker+ for constructing Entry elements.
|
934
|
+
def setup_maker(maker)
|
935
|
+
maker = maker.maker if maker.respond_to?("maker")
|
936
|
+
super(maker)
|
937
|
+
end
|
938
|
+
|
939
|
+
# Returns where there are any authors present or there is a
|
940
|
+
# source with an author.
|
941
|
+
def have_author?
|
942
|
+
authors.any? {|author| !author.to_s.empty?} or
|
943
|
+
(source and source.have_author?)
|
944
|
+
end
|
945
|
+
|
946
|
+
private
|
947
|
+
def atom_validate(ignore_unknown_element, tags, uri)
|
948
|
+
unless have_author?
|
949
|
+
raise MissingTagError.new("author", tag_name)
|
950
|
+
end
|
951
|
+
validate_duplicate_links(links)
|
952
|
+
end
|
953
|
+
|
954
|
+
def have_required_elements?
|
955
|
+
super and have_author?
|
956
|
+
end
|
957
|
+
|
958
|
+
def maker_target(maker)
|
959
|
+
maker.items.new_item
|
960
|
+
end
|
961
|
+
|
962
|
+
# Feed::Entry::Author
|
963
|
+
Author = Feed::Entry::Author
|
964
|
+
# Feed::Entry::Category
|
965
|
+
Category = Feed::Entry::Category
|
966
|
+
# Feed::Entry::Content
|
967
|
+
Content = Feed::Entry::Content
|
968
|
+
# Feed::Entry::Contributor
|
969
|
+
Contributor = Feed::Entry::Contributor
|
970
|
+
# Feed::Entry::Id
|
971
|
+
Id = Feed::Entry::Id
|
972
|
+
# Feed::Entry::Link
|
973
|
+
Link = Feed::Entry::Link
|
974
|
+
# Feed::Entry::Published
|
975
|
+
Published = Feed::Entry::Published
|
976
|
+
# Feed::Entry::Rights
|
977
|
+
Rights = Feed::Entry::Rights
|
978
|
+
# Feed::Entry::Source
|
979
|
+
Source = Feed::Entry::Source
|
980
|
+
# Feed::Entry::Summary
|
981
|
+
Summary = Feed::Entry::Summary
|
982
|
+
# Feed::Entry::Title
|
983
|
+
Title = Feed::Entry::Title
|
984
|
+
# Feed::Entry::Updated
|
985
|
+
Updated = Feed::Entry::Updated
|
986
|
+
end
|
987
|
+
end
|
988
|
+
|
989
|
+
Atom::CommonModel::ELEMENTS.each do |name|
|
990
|
+
BaseListener.install_get_text_element(Atom::URI, name, "#{name}=")
|
991
|
+
end
|
992
|
+
|
993
|
+
module ListenerMixin
|
994
|
+
private
|
995
|
+
def initial_start_feed(tag_name, prefix, attrs, ns)
|
996
|
+
check_ns(tag_name, prefix, ns, Atom::URI, false)
|
997
|
+
|
998
|
+
@rss = Atom::Feed.new(@version, @encoding, @standalone)
|
999
|
+
@rss.do_validate = @do_validate
|
1000
|
+
@rss.xml_stylesheets = @xml_stylesheets
|
1001
|
+
@rss.lang = attrs["xml:lang"]
|
1002
|
+
@rss.base = attrs["xml:base"]
|
1003
|
+
@last_element = @rss
|
1004
|
+
pr = Proc.new do |text, tags|
|
1005
|
+
@rss.validate_for_stream(tags) if @do_validate
|
1006
|
+
end
|
1007
|
+
@proc_stack.push(pr)
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
def initial_start_entry(tag_name, prefix, attrs, ns)
|
1011
|
+
check_ns(tag_name, prefix, ns, Atom::URI, false)
|
1012
|
+
|
1013
|
+
@rss = Atom::Entry.new(@version, @encoding, @standalone)
|
1014
|
+
@rss.do_validate = @do_validate
|
1015
|
+
@rss.xml_stylesheets = @xml_stylesheets
|
1016
|
+
@rss.lang = attrs["xml:lang"]
|
1017
|
+
@rss.base = attrs["xml:base"]
|
1018
|
+
@last_element = @rss
|
1019
|
+
pr = Proc.new do |text, tags|
|
1020
|
+
@rss.validate_for_stream(tags) if @do_validate
|
1021
|
+
end
|
1022
|
+
@proc_stack.push(pr)
|
1023
|
+
end
|
1024
|
+
end
|
1025
|
+
end
|