rrsimple-rss 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,213 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ require 'rdoc/task'
6
+ require 'rubygems/package_task'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+ require './lib/simple-rss'
9
+
10
+ PKG_VERSION = SimpleRSS::VERSION
11
+ PKG_NAME = "simple-rss"
12
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
13
+ RUBY_FORGE_PROJECT = "simple-rss"
14
+ RUBY_FORGE_USER = ENV['RUBY_FORGE_USER'] || "cardmagic"
15
+ RELEASE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
16
+
17
+ PKG_FILES = FileList[
18
+ "lib/*", "bin/*", "test/**/*", "[A-Z]*", "Rakefile", "html/**/*"
19
+ ]
20
+
21
+ desc "Default Task"
22
+ task :default => [ :test ]
23
+
24
+ # Run the unit tests
25
+ desc "Run all unit tests"
26
+ Rake::TestTask.new("test") { |t|
27
+ t.libs << ["lib", "test"]
28
+ t.pattern = 'test/*/*_test.rb'
29
+ t.verbose = true
30
+ }
31
+
32
+ # Make a console, useful when working on tests
33
+ desc "Generate a test console"
34
+ task :console do
35
+ verbose( false ) { sh "irb -I lib/ -r 'simple-rss'" }
36
+ end
37
+
38
+ # Genereate the RDoc documentation
39
+ desc "Create documentation"
40
+ Rake::RDocTask.new("doc") { |rdoc|
41
+ rdoc.title = "Simple RSS - A Flexible RSS and Atom reader for Ruby"
42
+ rdoc.rdoc_dir = 'html'
43
+ rdoc.rdoc_files.include('README.markdown')
44
+ rdoc.rdoc_files.include('lib/*.rb')
45
+ }
46
+
47
+ # Genereate the package
48
+ spec = Gem::Specification.new do |s|
49
+
50
+ #### Basic information.
51
+
52
+ s.name = 'simple-rss'
53
+ s.version = PKG_VERSION
54
+ s.summary = <<-EOF
55
+ A simple, flexible, extensible, and liberal RSS and Atom reader for Ruby. It is designed to be backwards compatible with the standard RSS parser, but will never do RSS generation.
56
+ EOF
57
+ s.description = <<-EOF
58
+ A simple, flexible, extensible, and liberal RSS and Atom reader for Ruby. It is designed to be backwards compatible with the standard RSS parser, but will never do RSS generation.
59
+ EOF
60
+
61
+ #### Which files are to be included in this gem? Everything! (Except CVS directories.)
62
+
63
+ s.files = PKG_FILES
64
+
65
+ #### Load-time details: library and application (you will need one or both).
66
+
67
+ s.require_path = 'lib'
68
+
69
+ #### Documentation and testing.
70
+
71
+ s.has_rdoc = true
72
+
73
+ #### Author and project details.
74
+
75
+ s.author = "Lucas Carlson"
76
+ s.email = "lucas@rufy.com"
77
+ s.homepage = "https://github.com/cardmagic/simple-rss"
78
+ end
79
+
80
+ Gem::PackageTask.new(spec) do |pkg|
81
+ pkg.need_zip = true
82
+ pkg.need_tar = true
83
+ end
84
+
85
+ desc "Report code statistics (KLOCs, etc) from the application"
86
+ task :stats do
87
+ require 'code_statistics'
88
+ CodeStatistics.new(
89
+ ["Library", "lib"],
90
+ ["Units", "test"]
91
+ ).to_s
92
+ end
93
+
94
+ desc "Publish new documentation"
95
+ task :publish do
96
+ Rake::RubyForgePublisher.new('simple-rss', 'cardmagic').upload
97
+ end
98
+
99
+
100
+ desc "Publish the release files to RubyForge."
101
+ task :upload => [:package] do
102
+ files = ["gem", "tar.gz", "zip"].map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
103
+
104
+ if RUBY_FORGE_PROJECT then
105
+ require 'net/http'
106
+ require 'open-uri'
107
+
108
+ project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
109
+ project_data = open(project_uri) { |data| data.read }
110
+ group_id = project_data[/[?&]group_id=(\d+)/, 1]
111
+ raise "Couldn't get group id" unless group_id
112
+
113
+ # This echos password to shell which is a bit sucky
114
+ if ENV["RUBY_FORGE_PASSWORD"]
115
+ password = ENV["RUBY_FORGE_PASSWORD"]
116
+ else
117
+ print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
118
+ password = STDIN.gets.chomp
119
+ end
120
+
121
+ login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
122
+ data = [
123
+ "login=1",
124
+ "form_loginname=#{RUBY_FORGE_USER}",
125
+ "form_pw=#{password}"
126
+ ].join("&")
127
+ http.post("/account/login.php", data)
128
+ end
129
+
130
+ cookie = login_response["set-cookie"]
131
+ raise "Login failed" unless cookie
132
+ headers = { "Cookie" => cookie }
133
+
134
+ release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
135
+ release_data = open(release_uri, headers) { |data| data.read }
136
+ package_id = release_data[/[?&]package_id=(\d+)/, 1]
137
+ raise "Couldn't get package id" unless package_id
138
+
139
+ first_file = true
140
+ release_id = ""
141
+
142
+ files.each do |filename|
143
+ basename = File.basename(filename)
144
+ file_ext = File.extname(filename)
145
+ file_data = File.open(filename, "rb") { |file| file.read }
146
+
147
+ puts "Releasing #{basename}..."
148
+
149
+ release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
150
+ release_date = Time.now.strftime("%Y-%m-%d %H:%M")
151
+ type_map = {
152
+ ".zip" => "3000",
153
+ ".tgz" => "3110",
154
+ ".gz" => "3110",
155
+ ".gem" => "1400"
156
+ }; type_map.default = "9999"
157
+ type = type_map[file_ext]
158
+ boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
159
+
160
+ query_hash = if first_file then
161
+ {
162
+ "group_id" => group_id,
163
+ "package_id" => package_id,
164
+ "release_name" => RELEASE_NAME,
165
+ "release_date" => release_date,
166
+ "type_id" => type,
167
+ "processor_id" => "8000", # Any
168
+ "release_notes" => "",
169
+ "release_changes" => "",
170
+ "preformatted" => "1",
171
+ "submit" => "1"
172
+ }
173
+ else
174
+ {
175
+ "group_id" => group_id,
176
+ "release_id" => release_id,
177
+ "package_id" => package_id,
178
+ "step2" => "1",
179
+ "type_id" => type,
180
+ "processor_id" => "8000", # Any
181
+ "submit" => "Add This File"
182
+ }
183
+ end
184
+
185
+ query = "?" + query_hash.map do |(name, value)|
186
+ [name, URI.encode(value)].join("=")
187
+ end.join("&")
188
+
189
+ data = [
190
+ "--" + boundary,
191
+ "Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
192
+ "Content-Type: application/octet-stream",
193
+ "Content-Transfer-Encoding: binary",
194
+ "", file_data, ""
195
+ ].join("\x0D\x0A")
196
+
197
+ release_headers = headers.merge(
198
+ "Content-Type" => "multipart/form-data; boundary=#{boundary}"
199
+ )
200
+
201
+ target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
202
+ http.post(target + query, data, release_headers)
203
+ end
204
+
205
+ if first_file then
206
+ release_id = release_response.body[/release_id=(\d+)/, 1]
207
+ raise("Couldn't get release id") unless release_id
208
+ end
209
+
210
+ first_file = false
211
+ end
212
+ end
213
+ end
data/install.rb ADDED
@@ -0,0 +1,40 @@
1
+ require 'rbconfig'
2
+ require 'find'
3
+ require 'ftools'
4
+
5
+ include Config
6
+
7
+ # this was adapted from rdoc's install.rb by ways of Log4r
8
+
9
+ $sitedir = CONFIG["sitelibdir"]
10
+ unless $sitedir
11
+ version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
12
+ $libdir = File.join(CONFIG["libdir"], "ruby", version)
13
+ $sitedir = $:.find {|x| x =~ /site_ruby/ }
14
+ if !$sitedir
15
+ $sitedir = File.join($libdir, "site_ruby")
16
+ elsif $sitedir !~ Regexp.quote(version)
17
+ $sitedir = File.join($sitedir, version)
18
+ end
19
+ end
20
+
21
+ makedirs = %w{ shipping }
22
+ makedirs.each {|f| File::makedirs(File.join($sitedir, *f.split(/\//)))}
23
+
24
+ Dir.chdir("lib")
25
+ begin
26
+ require 'rubygems'
27
+ require 'rake'
28
+ rescue LoadError
29
+ puts
30
+ puts "Please install Gem and Rake from http://rubyforge.org/projects/rubygems and http://rubyforge.org/projects/rake"
31
+ puts
32
+ exit(-1)
33
+ end
34
+
35
+ files = FileList["**/*"]
36
+
37
+ # File::safe_unlink *deprecated.collect{|f| File.join($sitedir, f.split(/\//))}
38
+ files.each {|f|
39
+ File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true)
40
+ }
data/lib/simple-rss.rb ADDED
@@ -0,0 +1,168 @@
1
+ require 'cgi'
2
+ require 'time'
3
+
4
+ class SimpleRSS
5
+ VERSION = "1.3.2"
6
+
7
+ attr_reader :items, :source
8
+ alias :entries :items
9
+
10
+ @@feed_tags = [
11
+ :id,
12
+ :title, :subtitle, :link,
13
+ :description,
14
+ :author, :webMaster, :managingEditor, :contributor,
15
+ :pubDate, :lastBuildDate, :updated, :'dc:date',
16
+ :generator, :language, :docs, :cloud,
17
+ :ttl, :skipHours, :skipDays,
18
+ :image, :logo, :icon, :rating,
19
+ :rights, :copyright,
20
+ :textInput, :'feedburner:browserFriendly',
21
+ :'itunes:author', :'itunes:category', :"full-text"
22
+ ]
23
+
24
+ @@item_tags = [
25
+ :id,
26
+ :title, :link, :'link+alternate', :'link+self', :'link+edit', :'link+replies',
27
+ :author, :contributor,
28
+ :description, :summary, :content, :'content:encoded', :comments,
29
+ :pubDate, :published, :updated, :expirationDate, :modified, :'dc:date',
30
+ :category, :guid,
31
+ :'trackback:ping', :'trackback:about',
32
+ :'dc:creator', :'dc:title', :'dc:subject', :'dc:rights', :'dc:publisher',
33
+ :'feedburner:origLink',
34
+ :'media:content#url', :'media:content#type', :'media:content#height', :'media:content#width',
35
+ :'media:title', :'media:thumbnail#url', :'media:thumbnail#height', :'media:thumbnail#width',
36
+ :'media:credit', :'media:credit#role',
37
+ :'media:category', :'media:category#scheme', :"full-text"
38
+ ]
39
+
40
+ def initialize(source, options={})
41
+ @source = source.respond_to?(:read) ? source.read : source.to_s
42
+ @items = Array.new
43
+ @options = Hash.new.update(options)
44
+
45
+ parse
46
+ end
47
+
48
+ def channel() self end
49
+ alias :feed :channel
50
+
51
+ class << self
52
+ def feed_tags
53
+ @@feed_tags
54
+ end
55
+ def feed_tags=(ft)
56
+ @@feed_tags = ft
57
+ end
58
+
59
+ def item_tags
60
+ @@item_tags
61
+ end
62
+ def item_tags=(it)
63
+ @@item_tags = it
64
+ end
65
+
66
+ # The strict attribute is for compatibility with Ruby's standard RSS parser
67
+ def parse(source, options={})
68
+ new source, options
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def parse
75
+ raise SimpleRSSError, "Poorly formatted feed" unless @source =~ %r{<(channel|feed).*?>.*?</(channel|feed)>}mi
76
+
77
+ # Feed's title and link
78
+ feed_content = $1 if @source =~ %r{(.*?)<(rss:|atom:)?(item|entry).*?>.*?</(rss:|atom:)?(item|entry)>}mi
79
+
80
+ @@feed_tags.each do |tag|
81
+ if feed_content && feed_content =~ %r{<(rss:|atom:)?#{tag}(.*?)>(.*?)</(rss:|atom:)?#{tag}>}mi
82
+ nil
83
+ elsif feed_content && feed_content =~ %r{<(rss:|atom:)?#{tag}(.*?)\/\s*>}mi
84
+ nil
85
+ elsif @source =~ %r{<(rss:|atom:)?#{tag}(.*?)>(.*?)</(rss:|atom:)?#{tag}>}mi
86
+ nil
87
+ elsif @source =~ %r{<(rss:|atom:)?#{tag}(.*?)\/\s*>}mi
88
+ nil
89
+ end
90
+
91
+ if $2 || $3
92
+ tag_cleaned = clean_tag(tag)
93
+ instance_variable_set("@#{ tag_cleaned }", clean_content(tag, $2, $3))
94
+ self.class.class_eval("attr_reader :#{ tag_cleaned }")
95
+ end
96
+ end
97
+
98
+ # RSS items' title, link, and description
99
+ @source.scan( %r{<(rss:|atom:)?(item|entry)([\s][^>]*)?>(.*?)</(rss:|atom:)?(item|entry)>}mi ) do |match|
100
+ item = Hash.new
101
+ @@item_tags.each do |tag|
102
+ if tag.to_s.include?("+")
103
+ tag_data = tag.to_s.split("+")
104
+ tag = tag_data[0]
105
+ rel = tag_data[1]
106
+
107
+ if match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)rel=['"]#{rel}['"](.*?)>(.*?)</(rss:|atom:)?#{tag}>}mi
108
+ nil
109
+ elsif match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)rel=['"]#{rel}['"](.*?)/\s*>}mi
110
+ nil
111
+ end
112
+ item[clean_tag("#{tag}+#{rel}")] = clean_content(tag, $3, $4) if $3 || $4
113
+ elsif tag.to_s.include?("#")
114
+ tag_data = tag.to_s.split("#")
115
+ tag = tag_data[0]
116
+ attrib = tag_data[1]
117
+ if match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)#{attrib}=['"](.*?)['"](.*?)>(.*?)</(rss:|atom:)?#{tag}>}mi
118
+ nil
119
+ elsif match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)#{attrib}=['"](.*?)['"](.*?)/\s*>}mi
120
+ nil
121
+ end
122
+ item[clean_tag("#{tag}_#{attrib}")] = clean_content(tag, attrib, $3) if $3
123
+ else
124
+ if match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)>(.*?)</(rss:|atom:)?#{tag}>}mi
125
+ nil
126
+ elsif match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)/\s*>}mi
127
+ nil
128
+ end
129
+ item[clean_tag(tag)] = clean_content(tag, $2, $3) if $2 || $3
130
+ end
131
+ end
132
+
133
+ def item.method_missing(name, *args) self[name] end
134
+
135
+ @items << item
136
+ end
137
+
138
+ end
139
+
140
+ def clean_content(tag, attrs, content)
141
+ content = content.to_s
142
+ case tag
143
+ when :pubDate, :lastBuildDate, :published, :updated, :expirationDate, :modified, :'dc:date'
144
+ Time.parse(content) rescue unescape(content)
145
+ when :author, :contributor, :skipHours, :skipDays
146
+ unescape(content.gsub(/<.*?>/,''))
147
+ when :"full-text"
148
+ CGI.unescapeHTML unescape(content.gsub(/<.*?>/,'')).force_encoding("UTF-8")
149
+ else
150
+ content.empty? && "#{attrs} " =~ /href=['"]?([^'"]*)['" ]/mi ? $1.strip : unescape(content)
151
+ end
152
+ end
153
+
154
+ def clean_tag(tag)
155
+ tag != :'full-text' ? tag.to_s.gsub(':','_').intern : tag.to_s.gsub('-','_').intern
156
+ end
157
+
158
+ def unescape(content)
159
+ if content.respond_to?(:force_encoding) && content.force_encoding("binary") =~ /([^-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]%)/n then
160
+ CGI.unescape(content).gsub(/(<!\[CDATA\[|\]\]>)/,'').strip
161
+ else
162
+ content.gsub(/(<!\[CDATA\[|\]\]>)/,'').strip
163
+ end
164
+ end
165
+ end
166
+
167
+ class SimpleRSSError < StandardError
168
+ end
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "rrsimple-rss"
3
+ s.version = "1.3.2"
4
+ s.date = "2010-07-06"
5
+ s.summary = "A simple, flexible, extensible, and liberal RSS and Atom reader for Ruby. It is designed to be backwards compatible with the standard RSS parser, but will never do RSS generation."
6
+ s.email = "rodrigo@rrmartins.com"
7
+ s.homepage = "http://github.com/cardmagic/simple-rss"
8
+ s.description = "A simple, flexible, extensible, and liberal RSS and Atom reader for Ruby. It is designed to be backwards compatible with the standard RSS parser, but will never do RSS generation."
9
+ s.has_rdoc = true
10
+ s.authors = ["Lucas Carlson", "Rodrigo Martins"]
11
+ s.files = ["install.rb", "lib", "lib/simple-rss.rb", "LICENSE", "Rakefile", "README.markdown", "simple-rss.gemspec", "test", "test/base", "test/base/base_test.rb", "test/data", "test/data/atom.xml", "test/data/not-rss.xml", "test/data/rss09.rdf", "test/data/rss20.xml", "test/test_helper.rb"]
12
+ s.rubyforge_project = 'rrsimple-rss'
13
+ end
@@ -0,0 +1,95 @@
1
+ #!/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require 'test_helper'
5
+ require 'pry'
6
+
7
+ class BaseTest < Test::Unit::TestCase
8
+ def setup
9
+ @rss_bbc = SimpleRSS.parse open(File.dirname(__FILE__) + '/../data/bbc.xml')
10
+ @rss09 = SimpleRSS.parse open(File.dirname(__FILE__) + '/../data/rss09.rdf')
11
+ @rss20 = SimpleRSS.parse open(File.dirname(__FILE__) + '/../data/rss20.xml')
12
+ @media_rss = SimpleRSS.parse open(File.dirname(__FILE__) + '/../data/media_rss.xml')
13
+ @atom = SimpleRSS.parse open(File.dirname(__FILE__) + '/../data/atom.xml')
14
+ end
15
+
16
+ def test_channel
17
+ assert_equal @rss_bbc, @rss_bbc.channel
18
+ assert_equal @rss09, @rss09.channel
19
+ assert_equal @rss20, @rss20.channel
20
+ assert_equal @atom, @atom.feed
21
+ end
22
+
23
+ def test_items
24
+ assert_kind_of Array, @rss_bbc.items
25
+ assert_kind_of Array, @rss09.items
26
+ assert_kind_of Array, @rss20.items
27
+ assert_kind_of Array, @atom.entries
28
+ end
29
+
30
+ def test_rss_bbc
31
+ assert_equal 9, @rss_bbc.items.size
32
+ assert_equal "BBCBrasil.com | Vídeos e Fotos", @rss_bbc.title.force_encoding("UTF-8")
33
+ assert_equal "http://www.bbc.com/portuguese/full_all.xml", @rss_bbc.channel.link
34
+ assert_equal "http://www.bbc.com/portuguese/noticias/2015/11/151102_nadador_atlantico_desafio_lgb", @rss_bbc.items.first.link
35
+ assert_equal "http://www.bbc.com/portuguese/noticias/2015/11/151102_nadador_atlantico_desafio_lgb", @rss_bbc.items.first[:link]
36
+ assert_equal Time.parse("2015-11-03 08:21:50 -0200"), @rss_bbc.items.first.pubDate
37
+ assert_equal Time.parse("2015-11-05 07:33:38 -0200"), @rss_bbc.channel.lastBuildDate
38
+ assert_not_nil @rss_bbc.items.first.full_text
39
+ end
40
+
41
+ def test_rss09
42
+ assert_equal 10, @rss09.items.size
43
+ assert_equal "Slashdot", @rss09.title
44
+ assert_equal "http://slashdot.org/", @rss09.channel.link
45
+ assert_equal "http://books.slashdot.org/article.pl?sid=05/08/29/1319236&amp;from=rss", @rss09.items.first.link
46
+ assert_equal "http://books.slashdot.org/article.pl?sid=05/08/29/1319236&amp;from=rss", @rss09.items.first[:link]
47
+ assert_equal Time.parse("2005-09-09 06:52:31 -0300"), @rss09.items.first.dc_date
48
+ assert_equal Time.parse("Fri Sep 09 02:52:31 PDT 2005"), @rss09.channel.dc_date
49
+ assert_nil @rss09.items.first.full_text
50
+ end
51
+
52
+ def test_media_rss
53
+ assert_equal 20, @media_rss.items.size
54
+ assert_equal "Uploads from herval", @media_rss.title
55
+ assert_equal "http://www.flickr.com/photos/herval/", @media_rss.channel.link
56
+ assert_equal "http://www.flickr.com/photos/herval/4671960608/", @media_rss.items.first.link
57
+ assert_equal "http://www.flickr.com/photos/herval/4671960608/", @media_rss.items.first[:link]
58
+ assert_equal "http://farm5.static.flickr.com/4040/4671960608_10cb945d5c_o.jpg", @media_rss.items.first.media_content_url
59
+ assert_equal "image/jpeg", @media_rss.items.first.media_content_type
60
+ assert_equal "3168", @media_rss.items.first.media_content_height
61
+ assert_equal "4752", @media_rss.items.first.media_content_width
62
+ assert_equal "Woof?", @media_rss.items.first.media_title
63
+ assert_equal "http://farm5.static.flickr.com/4040/4671960608_954d2297bc_s.jpg", @media_rss.items.first.media_thumbnail_url
64
+ assert_equal "75", @media_rss.items.first.media_thumbnail_height
65
+ assert_equal "75", @media_rss.items.first.media_thumbnail_width
66
+ assert_equal "herval", @media_rss.items.first.media_credit
67
+ assert_equal "photographer", @media_rss.items.first.media_credit_role
68
+ assert_equal "pets frodo", @media_rss.items.first.media_category
69
+ assert_equal "urn:flickr:tags", @media_rss.items.first.media_category_scheme
70
+ assert_nil @media_rss.items.first.full_text
71
+ end
72
+
73
+ def test_rss20
74
+ assert_equal 10, @rss20.items.size
75
+ assert_equal "Technoblog", @rss20.title
76
+ assert_equal "http://tech.rufy.com", @rss20.channel.link
77
+ assert_equal "http://feeds.feedburner.com/rufytech?m=68", @rss20.items.first.link
78
+ assert_equal "http://feeds.feedburner.com/rufytech?m=68", @rss20.items.first[:link]
79
+ assert_equal "This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site.", @rss20.channel.feedburner_browserFriendly
80
+ assert_nil @rss20.items.first.full_text
81
+ end
82
+
83
+ def test_atom
84
+ assert_equal 1, @atom.entries.size
85
+ assert_equal "dive into mark", @atom.title
86
+ assert_equal "http://example.org/", @atom.feed.link
87
+ assert_equal "http://example.org/2005/04/02/atom", @atom.entries.first.link
88
+ assert_equal "http://example.org/2005/04/02/atom", @atom.entries.first[:link]
89
+ assert_nil @atom.entries.first.full_text
90
+ end
91
+
92
+ def test_bad_feed
93
+ assert_raise(SimpleRSSError) { SimpleRSS.parse(open(File.dirname(__FILE__) + '/../data/not-rss.xml')) }
94
+ end
95
+ end
@@ -0,0 +1,45 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <feed xmlns="http://www.w3.org/2005/Atom">
3
+ <rss:title type="text">dive into mark</title>
4
+ <subtitle type="html">
5
+ A &lt;em&gt;lot&lt;/em&gt; of effort
6
+ went into making this effortless
7
+ </subtitle>
8
+ <updated>2005-07-31T12:29:29Z</updated>
9
+ <id>tag:example.org,2003:3</id>
10
+ <link rel="alternate" type="text/html"
11
+ hreflang="en" href="http://example.org/"/>
12
+ <link rel="self" type="application/atom+xml"
13
+ href="http://example.org/feed.atom"/>
14
+ <rights>Copyright (c) 2003, Mark Pilgrim</rights>
15
+ <generator uri="http://www.example.com/" version="1.0">
16
+ Example Toolkit
17
+ </generator>
18
+ <entry>
19
+ <title>Atom draft-07 snapshot</title>
20
+ <link rel="alternate" type="text/html"
21
+ href="http://example.org/2005/04/02/atom"/>
22
+ <link rel="enclosure" type="audio/mpeg" length="1337"
23
+ href="http://example.org/audio/ph34r_my_podcast.mp3"/>
24
+ <id>tag:example.org,2003:3.2397</id>
25
+ <updated>2005-07-31T12:29:29Z</updated>
26
+ <published>2003-12-13T08:29:29-04:00</published>
27
+ <author>
28
+ <name>Mark Pilgrim</name>
29
+ <uri>http://example.org/</uri>
30
+ <email>f8dy@example.com</email>
31
+ </author>
32
+ <contributor>
33
+ <name>Sam Ruby</name>
34
+ </contributor>
35
+ <contributor>
36
+ <name>Joe Gregorio</name>
37
+ </contributor>
38
+ <content type="xhtml" xml:lang="en"
39
+ xml:base="http://diveintomark.org/">
40
+ <div xmlns="http://www.w3.org/1999/xhtml">
41
+ <p><i>[Update: The Atom draft is finished.]</i></p>
42
+ </div>
43
+ </content>
44
+ </entry>
45
+ </feed>
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head>
3
+ <title>This ain't RSS!</title>
4
+ </head>
5
+ <body>
6
+ No, this is HTML, not RSS.
7
+ </body>
8
+ </html>
@@ -0,0 +1,79 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+
3
+ <rdf:RDF
4
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
5
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
6
+ xmlns="http://my.netscape.com/rdf/simple/0.9/">
7
+
8
+ <channel>
9
+ <title>Slashdot</title>
10
+ <link>http://slashdot.org/</link>
11
+ <description>News for nerds, stuff that matters</description>
12
+ <dc:date>2005-09-09T02:52:31-07:00</dc:date>
13
+ </channel>
14
+
15
+ <image>
16
+ <title>Slashdot</title>
17
+ <url>http://images.slashdot.org/topics/topicslashdot.gif</url>
18
+ <link>http://slashdot.org/</link>
19
+ </image>
20
+
21
+ <item>
22
+ <title>JBoss - A Developer's Notebook</title>
23
+ <link>http://books.slashdot.org/article.pl?sid=05/08/29/1319236&amp;from=rss</link>
24
+ <dc:date>2005-09-09T02:52:31-07:00</dc:date>
25
+ </item>
26
+
27
+ <item>
28
+ <title>Apple Hedges Its Bet on New Intel Chips</title>
29
+ <link>http://hardware.slashdot.org/article.pl?sid=05/08/29/1314219&amp;from=rss</link>
30
+ </item>
31
+
32
+ <item>
33
+ <title>Beowulf Pioneer Lured From Cal Tech to LSU</title>
34
+ <link>http://slashdot.org/article.pl?sid=05/08/29/1035240&amp;from=rss</link>
35
+ </item>
36
+
37
+ <item>
38
+ <title>Google Talk Claims Openness, Lacks S2S Support</title>
39
+ <link>http://it.slashdot.org/article.pl?sid=05/08/29/1022242&amp;from=rss</link>
40
+ </item>
41
+
42
+ <item>
43
+ <title>The End of the Bar Code</title>
44
+ <link>http://slashdot.org/article.pl?sid=05/08/29/1020220&amp;from=rss</link>
45
+ </item>
46
+
47
+ <item>
48
+ <title>2.6.13 Linux Kernel Released</title>
49
+ <link>http://linux.slashdot.org/article.pl?sid=05/08/29/0334205&amp;from=rss</link>
50
+ </item>
51
+
52
+ <item>
53
+ <title>HOWTO: The Anti-Printer</title>
54
+ <link>http://hardware.slashdot.org/article.pl?sid=05/08/29/1016204&amp;from=rss</link>
55
+ </item>
56
+
57
+ <item>
58
+ <title>OSDL Skeptical Of Joint Study with Microsoft</title>
59
+ <link>http://linux.slashdot.org/article.pl?sid=05/08/29/0625224&amp;from=rss</link>
60
+ </item>
61
+
62
+ <item>
63
+ <title>New Mad Cow Test on the Horizon?</title>
64
+ <link>http://science.slashdot.org/article.pl?sid=05/08/29/0619259&amp;from=rss</link>
65
+ </item>
66
+
67
+ <item>
68
+ <title>Coffee A Health Drink?</title>
69
+ <link>http://science.slashdot.org/article.pl?sid=05/08/29/0342207&amp;from=rss</link>
70
+ </item>
71
+
72
+ <textinput>
73
+ <title>Search Slashdot</title>
74
+ <description>Search Slashdot stories</description>
75
+ <name>query</name>
76
+ <link>http://slashdot.org/search.pl</link>
77
+ </textinput>
78
+
79
+ </rdf:RDF>