xommelier 0.1.16 → 0.1.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,136 @@
1
+ module Xommelier
2
+ module Xml
3
+ class Element
4
+ module Structure
5
+ class Property
6
+ def initialize(name, options)
7
+ @name = name
8
+ @options = self.class.const_get(:DEFAULTS).merge(options)
9
+ end
10
+
11
+ attr_reader :name, :options
12
+
13
+ def writer
14
+ @writer ||= "#{name}="
15
+ end
16
+
17
+ # @return [Xommelier::Xml::Namespace]
18
+ def ns
19
+ options[:ns]
20
+ end
21
+
22
+ def default
23
+ options[:default]
24
+ end
25
+
26
+ # @return [Class]
27
+ def type
28
+ options[:type]
29
+ end
30
+
31
+ # @return [true, false] has default value?
32
+ def default?
33
+ options.key?(:default) && required?
34
+ end
35
+
36
+ def inspect
37
+ "#<Xommelier::X::E::S::#{self.class.name.demodulize}:0x#{object_id.to_s(16)} #{instance_variables.map { |ivar| "#{ivar}=#{instance_variable_get(ivar).inspect}"}.join(' ')}>"
38
+ end
39
+
40
+ protected
41
+
42
+ def overrides
43
+ @overrides ||= {}
44
+ end
45
+ end
46
+
47
+ class Element < Property
48
+ DEFAULTS = {
49
+ type: String,
50
+ count: :one
51
+ }
52
+
53
+ def node_type
54
+ :element
55
+ end
56
+
57
+ def element_name
58
+ @element_name ||= options.delete(:as) { name }.to_s
59
+ end
60
+
61
+ def serializable_element_name
62
+ @serializable_element_name ||= if %w(class id text).include?(element_name)
63
+ element_name + '_'
64
+ else
65
+ element_name
66
+ end
67
+ end
68
+
69
+ def required?
70
+ options[:count] == :one || options[:count] == :many
71
+ end
72
+
73
+ def multiple?
74
+ return overrides[:multiple] if overrides.key?(:multiple)
75
+ options[:count] == :many || options[:count] == :any
76
+ end
77
+
78
+ def plural
79
+ @plural ||= name.to_s.pluralize.to_sym
80
+ end
81
+
82
+ def plural_writer
83
+ @plural_writer ||= "#{plural}="
84
+ end
85
+
86
+ def numbers_equal?
87
+ plural == name
88
+ end
89
+
90
+ def overridden_xmlns
91
+ overrides[:xmlns]
92
+ end
93
+
94
+ def override(overrides)
95
+ @overrides = overrides
96
+ yield
97
+ @overrides = {}
98
+ end
99
+ end
100
+
101
+ class Attribute < Property
102
+ DEFAULTS = {
103
+ type: String,
104
+ required: false
105
+ }
106
+
107
+ def node_type
108
+ :attribute
109
+ end
110
+
111
+ def required?
112
+ options[:required]
113
+ end
114
+
115
+ def attribute_name
116
+ @attribute_name ||= options.delete(:as) { name }.to_s
117
+ end
118
+ end
119
+
120
+ class Text < Property
121
+ DEFAULTS = {
122
+ type: String
123
+ }
124
+
125
+ def node_type
126
+ :text
127
+ end
128
+
129
+ def required?
130
+ options[:required]
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
@@ -81,8 +81,12 @@ module Xommelier
81
81
  {as.to_s => uri.to_s}
82
82
  end
83
83
 
84
+ def attribute_name
85
+ default? ? 'xmlns' : "xmlns:#{as}"
86
+ end
87
+
84
88
  def inspect
85
- %(xmlns:#{as}="#{uri}")
89
+ %(#{attribute_name}="#{uri}")
86
90
  end
87
91
  end
88
92
  end
@@ -0,0 +1,41 @@
1
+ <?xml version="1.0"?>
2
+ <rss version="2.0">
3
+ <channel>
4
+ <title>Liftoff News</title>
5
+ <link>http://liftoff.msfc.nasa.gov/</link>
6
+ <description>Liftoff to Space Exploration.</description>
7
+ <language>en-us</language>
8
+ <pubDate>Tue, 10 Jun 2003 04:00:00 GMT</pubDate>
9
+ <lastBuildDate>Tue, 10 Jun 2003 09:41:01 GMT</lastBuildDate>
10
+ <docs>http://blogs.law.harvard.edu/tech/rss</docs>
11
+ <generator>Weblog Editor 2.0</generator>
12
+ <managingEditor>editor@example.com</managingEditor>
13
+ <webMaster>webmaster@example.com</webMaster>
14
+ <item>
15
+ <title>Star City</title>
16
+ <link>http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp</link>
17
+ <description>How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's &lt;a href="http://howe.iki.rssi.ru/GCTC/gctc_e.htm"&gt;Star City&lt;/a&gt;.</description>
18
+ <pubDate>Tue, 03 Jun 2003 09:39:21 GMT</pubDate>
19
+ <guid>http://liftoff.msfc.nasa.gov/2003/06/03.html#item573</guid>
20
+ </item>
21
+ <item>
22
+ <description>Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a &lt;a href="http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm"&gt;partial eclipse of the Sun&lt;/a&gt; on Saturday, May 31st.</description>
23
+ <pubDate>Fri, 30 May 2003 11:06:42 GMT</pubDate>
24
+ <guid>http://liftoff.msfc.nasa.gov/2003/05/30.html#item572</guid>
25
+ </item>
26
+ <item>
27
+ <title>The Engine That Does More</title>
28
+ <link>http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp</link>
29
+ <description>Before man travels to Mars, NASA hopes to design new engines that will let us fly through the Solar System more quickly. The proposed VASIMR engine would do that.</description>
30
+ <pubDate>Tue, 27 May 2003 08:37:32 GMT</pubDate>
31
+ <guid>http://liftoff.msfc.nasa.gov/2003/05/27.html#item571</guid>
32
+ </item>
33
+ <item>
34
+ <title>Astronauts' Dirty Laundry</title>
35
+ <link>http://liftoff.msfc.nasa.gov/news/2003/news-laundry.asp</link>
36
+ <description>Compared to earlier spacecraft, the International Space Station has many luxuries, but laundry facilities are not one of them. Instead, astronauts have other options.</description>
37
+ <pubDate>Tue, 20 May 2003 08:56:02 GMT</pubDate>
38
+ <guid>http://liftoff.msfc.nasa.gov/2003/05/20.html#item570</guid>
39
+ </item>
40
+ </channel>
41
+ </rss>
@@ -0,0 +1,78 @@
1
+ <rss version="2.0"
2
+ xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"
3
+ xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
4
+ <channel>
5
+ <creativeCommons:license>http://www.creativecommons.org/licenses/by-nd/1.0</creativeCommons:license>
6
+ <description>Current headlines from the Dallas Times-Herald newspaper</description>
7
+ <link>http://dallas.example.com</link>
8
+ <title>Dallas Times-Herald</title>
9
+ <category>Media</category>
10
+ <category domain="Newspapers/Regional/United_States">Texas</category>
11
+ <cloud domain="server.example.com" path="/rpc" port="80" protocol="xml-rpc" registerProcedure="cloud.notify" />
12
+ <copyright>Copyright 2006 Dallas Times-Herald</copyright>
13
+ <docs>http://www.rssboard.org/rss-specification</docs>
14
+ <generator>Radio UserLand v8.2.1</generator>
15
+ <image>
16
+ <link>http://dallas.example.com</link>
17
+ <title>Dallas Times-Herald</title>
18
+ <url>http://dallas.example.com/masthead.gif</url>
19
+ <description>Read the Dallas Times-Herald</description>
20
+ <height>32</height>
21
+ <width>96</width>
22
+ </image>
23
+ <language>epo</language>
24
+ <lastBuildDate>Sun, 29 Jan 2006 17:17:44 GMT</lastBuildDate>
25
+ <managingEditor>jlehrer@dallas.example.com (Jim Lehrer)</managingEditor>
26
+ <pubDate>Sun, 29 Jan 2006 05:00:00 GMT</pubDate>
27
+ <rating>(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l by "webmaster@example.com" on "2006.01.29T10:09-0800" r (n 0 s 0 v 0 l 0))</rating>
28
+ <skipDays>
29
+ <day>Saturday</day>
30
+ <day>Sunday</day>
31
+ </skipDays>
32
+ <skipHours>
33
+ <hour>0</hour>
34
+ <hour>1</hour>
35
+ <hour>2</hour>
36
+ <hour>22</hour>
37
+ <hour>23</hour>
38
+ </skipHours>
39
+ <textInput>
40
+ <description>Your aggregator supports the textInput element. What software are you using?</description>
41
+ <link>http://www.cadenhead.org/textinput.php</link>
42
+ <name>query</name>
43
+ <title>TextInput Inquiry</title>
44
+ </textInput>
45
+ <ttl>60</ttl>
46
+ <webMaster>helpdesk@dallas.example.com</webMaster>
47
+ <item>
48
+ <trackback:ping>http://dallas.example.com/trackback/tb.php?id=1991/05/02/nolan.htm</trackback:ping>
49
+ <title>Seventh Heaven! Ryan Hurls Another No Hitter</title>
50
+ <link>http://dallas.example.com/1991/05/02/nolan.htm</link>
51
+ <description>Texas Rangers pitcher Nolan Ryan hurled the seventh no-hitter of his legendary career on Arlington Appreciation Night, defeating the Toronto Blue Jays 3-0. The 44-year-old struck out 16 batters before a crowd of 33,439.</description>
52
+ <guid>http://dallas.example.com/1991/05/02/nolan.htm</guid>
53
+ </item>
54
+ <item>
55
+ <trackback:ping>http://dallas.example.com/trackback/tb.php?id=1983/06/joebob.htm</trackback:ping>
56
+ <author>jbb@dallas.example.com (Joe Bob Briggs)</author>
57
+ <category>rec.arts.movies.reviews</category>
58
+ <comments>http://dallas.example.com/feedback/1983/06/joebob.htm</comments>
59
+ <description>I'm headed for France. I wasn't gonna go this year, but then last week "Valley Girl" came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description>
60
+ <enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
61
+ <guid>http://dallas.example.com/1983/05/06/joebob.htm</guid>
62
+ <link>http://dallas.example.com/1983/05/06/joebob.htm</link>
63
+ <pubDate>Fri, 06 May 1983 09:00:00 CST</pubDate>
64
+ <source url="http://la.example.com/rss.xml">Los Angeles Herald-Examiner</source>
65
+ <title>Joe Bob Goes to the Drive-In</title>
66
+ </item>
67
+ <item>
68
+ <trackback:ping>http://dallas.example.com/trackback/tb.php?id=1983/06/joebob2.htm</trackback:ping>
69
+ <trackback:about>http://www.imdb.com/title/tt0086525/</trackback:about>
70
+ <description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description>
71
+ <guid isPermaLink="false">tag:dallas.example.com,4131:news</guid>
72
+ </item>
73
+ <item>
74
+ <description><![CDATA[I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.]]></description>
75
+ <guid isPermaLink="false">1983-05-06+lifestyle+joebob+2</guid>
76
+ </item>
77
+ </channel>
78
+ </rss>
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <rss version="2.0">
3
+ <channel>
4
+ <title>Example Feed</title>
5
+ <link>http://example.com</link>
6
+ <managingEditor>john.doe@example.com</managingEditor>
7
+ <pubDate>Tue, 10 Jun 2003 04:00:00 -0000</pubDate>
8
+ <lastBuildDate>Sat, 13 Dec 2003 18:30:02 -0000</lastBuildDate>
9
+ <item>
10
+ <guid>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</guid>
11
+ <title>RSS-Powered Robots Run Amok</title>
12
+ <description>Some text.</description>
13
+ <link>http://example.org/2003/12/13/atom03</link>
14
+ <pubDate>Sat, 13 Dec 2003 18:30:02 -0000</pubDate>
15
+ </item>
16
+ </channel>
17
+ </rss>
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'Atom feed building' do
4
- let(:feed) do
4
+ subject(:feed) do
5
5
  Xommelier::Atom::Feed.new.tap do |feed|
6
6
  feed.id = 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6'
7
7
  feed.title = 'Example Feed'
@@ -19,21 +19,13 @@ describe 'Atom feed building' do
19
19
  end
20
20
  end
21
21
 
22
- let(:built_xml) { feed.to_xml }
23
- let(:parsed_xml) { Nokogiri::XML(built_xml) }
22
+ let(:parsed_xml) { Nokogiri::XML(feed.to_xml) }
24
23
  let(:rng) { Nokogiri::XML::RelaxNG(load_xml_file('atom.rng')) }
25
- let(:xsd) { Nokogiri::XML::Schema(load_xml_file('atom.xsd')) }
24
+ let(:xsd) { Xommelier::Atom.schema }
26
25
 
27
- subject { built_xml }
26
+ it { should be_valid }
28
27
 
29
- it { feed.should be_valid }
30
-
31
- it { should == load_xml_file('simple_feed.atom').read }
32
- it do
33
- rng.validate(parsed_xml).each do |error|
34
- pp error
35
- end
36
- end
28
+ its(:to_xml) { should == load_xml_file('simple_feed.atom') }
37
29
  it('should conform to RelaxNG schema') { rng.valid?(parsed_xml).should == true }
38
30
  it('should conform to XML Schema') { xsd.valid?(parsed_xml).should == true }
39
31
  end
@@ -35,6 +35,6 @@ describe 'Atom feed building' do
35
35
 
36
36
  subject { built_xml }
37
37
 
38
- it { should == load_xml_file('multi_namespace_feed.atom').read }
38
+ it { should == load_xml_file('multi_namespace_feed.atom') }
39
39
  it('should conform to RelaxNG schema') { rng.valid?(parsed_xml).should == true }
40
40
  end
@@ -26,7 +26,7 @@ describe 'Build document from nested hash' do
26
26
 
27
27
  subject { doc }
28
28
 
29
- its(:to_xml) { should == load_xml_file('nested_atom').read }
29
+ its(:to_xml) { should == load_xml_file('nested_atom') }
30
30
  it { should have(1).authors }
31
31
  it { should have(3).contributors }
32
32
  it { should have(3).entries }
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'RSS feed building' do
4
+ subject(:rss) do
5
+ Xommelier::RSS::Rss.new(
6
+ channel: {
7
+ title: 'Example Feed',
8
+ link: 'http://example.com',
9
+ pub_date: Time.utc(2003, 6, 10, 04),
10
+ last_build_date: Time.utc(2003, 12, 13, 18, 30, 02),
11
+ managing_editor: 'john.doe@example.com',
12
+ items: [{
13
+ title: 'RSS-Powered Robots Run Amok',
14
+ guid: 'urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a',
15
+ pub_date: Time.utc(2003, 12, 13, 18, 30, 02),
16
+ description: 'Some text.',
17
+ link: 'http://example.org/2003/12/13/atom03'
18
+ }]
19
+ }
20
+ )
21
+ end
22
+
23
+ it { should be_valid }
24
+ its(:to_xml) { should == load_xml_file('simple_feed.rss') }
25
+ end
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+ require 'spec_helper'
3
+ require 'active_support/core_ext/numeric/time'
4
+ require 'xommelier/rss'
5
+
6
+ describe 'RSS feed' do
7
+ describe 'parsing' do
8
+ let(:rss_xml) { load_xml_file('feed.rss2.0') }
9
+ let(:feed) { Xommelier::RSS::Rss.parse(rss_xml) }
10
+
11
+ subject { feed }
12
+
13
+ it { should be_kind_of(Xommelier::RSS::Rss) }
14
+
15
+ its(:title) { should == 'Liftoff News' }
16
+ its(:last_build_date) { should == Time.utc(2003, 6, 10, 9, 41, 01) }
17
+ its(:pub_date) { should == Time.utc(2003, 6, 10, 04) }
18
+ its(:description) { should == 'Liftoff to Space Exploration.' }
19
+ its(:link) { should == URI.parse('http://liftoff.msfc.nasa.gov/') }
20
+ its(:docs) { should == 'http://blogs.law.harvard.edu/tech/rss' }
21
+ its(:description) { should == 'Liftoff to Space Exploration.' }
22
+ its(:generator) { should == 'Weblog Editor 2.0' }
23
+ its(:managing_editor) { should == 'editor@example.com' }
24
+ its(:web_master) { should == 'webmaster@example.com' }
25
+
26
+ it { feed.should have(4).items }
27
+ describe 'Item' do
28
+ let(:item) { feed.items[0] }
29
+ subject { item }
30
+
31
+ its(:guid) { should be_an Xommelier::RSS::Guid }
32
+ its('guid.text') { should == 'http://liftoff.msfc.nasa.gov/2003/06/03.html#item573' }
33
+ its('guid.to_s') { should == 'http://liftoff.msfc.nasa.gov/2003/06/03.html#item573' }
34
+ its(:guid) { should == 'http://liftoff.msfc.nasa.gov/2003/06/03.html#item573' }
35
+ its(:title) { should == 'Star City' }
36
+ its(:pub_date) { should == Time.utc(2003, 6, 3, 9, 39, 21) }
37
+ its(:description) { should == 'How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia\'s <a href="http://howe.iki.rssi.ru/GCTC/gctc_e.htm">Star City</a>.' }
38
+ its(:link) { should == URI.parse('http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp') }
39
+ end
40
+ end
41
+ end
@@ -8,6 +8,7 @@ Dir[File.join(SPEC_ROOT, 'spec/support/**/*.rb')].each {|f| require f}
8
8
 
9
9
  ATOM_XMLNS = 'http://www.w3.org/2005/Atom'
10
10
 
11
+ #noinspection RubyResolve
11
12
  RSpec.configure do |config|
12
13
  config.mock_with :rspec
13
14
  config.order = 'random'
@@ -1,3 +1,3 @@
1
1
  def load_xml_file(file_name)
2
- open(File.join(SPEC_ROOT, 'spec', 'fixtures', "#{file_name}.xml"))
2
+ open(File.join(SPEC_ROOT, 'spec', 'fixtures', "#{file_name}.xml")).read
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xommelier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.16
4
+ version: 0.1.18
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-08 00:00:00.000000000 Z
12
+ date: 2013-01-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -93,6 +93,7 @@ files:
93
93
  - lib/xommelier/atom/source.rb
94
94
  - lib/xommelier/atom/threading.rb
95
95
  - lib/xommelier/collection.rb
96
+ - lib/xommelier/common.rb
96
97
  - lib/xommelier/core_ext.rb
97
98
  - lib/xommelier/core_ext/boolean.rb
98
99
  - lib/xommelier/core_ext/date.rb
@@ -103,23 +104,31 @@ files:
103
104
  - lib/xommelier/core_ext/time.rb
104
105
  - lib/xommelier/core_ext/uri.rb
105
106
  - lib/xommelier/open_search.rb
107
+ - lib/xommelier/opml.rb
108
+ - lib/xommelier/rss.rb
106
109
  - lib/xommelier/schemas/atom.xsd
110
+ - lib/xommelier/schemas/rss.xsd
107
111
  - lib/xommelier/version.rb
108
112
  - lib/xommelier/xml.rb
109
113
  - lib/xommelier/xml/element.rb
110
114
  - lib/xommelier/xml/element/serialization.rb
111
115
  - lib/xommelier/xml/element/structure.rb
116
+ - lib/xommelier/xml/element/structure/property.rb
112
117
  - lib/xommelier/xml/namespace.rb
113
118
  - spec/fixtures/atom.rng.xml
114
- - spec/fixtures/atom.xsd.xml
115
119
  - spec/fixtures/feed.atom.xml
120
+ - spec/fixtures/feed.rss2.0.xml
116
121
  - spec/fixtures/multi_namespace_feed.atom.xml
117
122
  - spec/fixtures/nested_atom.xml
123
+ - spec/fixtures/rss-2.0-namespace.xml
118
124
  - spec/fixtures/simple_feed.atom.xml
125
+ - spec/fixtures/simple_feed.rss.xml
119
126
  - spec/functional/atom_feed_building_spec.rb
120
127
  - spec/functional/atom_feed_parsing_spec.rb
121
128
  - spec/functional/atom_feed_thread_building_spec.rb
122
129
  - spec/functional/build_nested_document_from_hash_spec.rb
130
+ - spec/functional/rss_feed_building_spec.rb
131
+ - spec/functional/rss_feed_parsing_spec.rb
123
132
  - spec/lib/xommelier/atom/entry_spec.rb
124
133
  - spec/lib/xommelier/xml/element/serialization_spec.rb
125
134
  - spec/lib/xommelier/xml/element/structure_spec.rb
@@ -156,15 +165,19 @@ specification_version: 3
156
165
  summary: Xommelier is an XML Sommelier
157
166
  test_files:
158
167
  - spec/fixtures/atom.rng.xml
159
- - spec/fixtures/atom.xsd.xml
160
168
  - spec/fixtures/feed.atom.xml
169
+ - spec/fixtures/feed.rss2.0.xml
161
170
  - spec/fixtures/multi_namespace_feed.atom.xml
162
171
  - spec/fixtures/nested_atom.xml
172
+ - spec/fixtures/rss-2.0-namespace.xml
163
173
  - spec/fixtures/simple_feed.atom.xml
174
+ - spec/fixtures/simple_feed.rss.xml
164
175
  - spec/functional/atom_feed_building_spec.rb
165
176
  - spec/functional/atom_feed_parsing_spec.rb
166
177
  - spec/functional/atom_feed_thread_building_spec.rb
167
178
  - spec/functional/build_nested_document_from_hash_spec.rb
179
+ - spec/functional/rss_feed_building_spec.rb
180
+ - spec/functional/rss_feed_parsing_spec.rb
168
181
  - spec/lib/xommelier/atom/entry_spec.rb
169
182
  - spec/lib/xommelier/xml/element/serialization_spec.rb
170
183
  - spec/lib/xommelier/xml/element/structure_spec.rb