ratom 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/Manifest.txt +1 -0
- data/README.txt +44 -0
- data/lib/atom/version.rb +2 -2
- data/lib/atom/xml/parser.rb +27 -7
- data/spec/atom_spec.rb +44 -0
- data/spec/fixtures/with_stylesheet.atom +8 -0
- metadata +3 -2
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -36,6 +36,7 @@ spec/fixtures/created_entry.atom
|
|
36
36
|
spec/fixtures/entry.atom
|
37
37
|
spec/fixtures/multiple_entry.atom
|
38
38
|
spec/fixtures/simple_single_entry.atom
|
39
|
+
spec/fixtures/with_stylesheet.atom
|
39
40
|
spec/paging/first_paged_feed.atom
|
40
41
|
spec/paging/last_paged_feed.atom
|
41
42
|
spec/paging/middle_paged_feed.atom
|
data/README.txt
CHANGED
@@ -181,6 +181,50 @@ You can then call to_xml and rAtom will serialize the extension elements into xm
|
|
181
181
|
Notice that the output repeats the xmlns attribute for each of the extensions, this is semantically the same the input XML, just a bit
|
182
182
|
ugly. It seems to be a limitation of the libxml-Ruby API. But if anyone knows a work around I'd gladly accept a patch (or even advice).
|
183
183
|
|
184
|
+
==== Custom Extension Classes
|
185
|
+
|
186
|
+
As of version 0.5.0 you can also define your own classes for a extension elements. This is done by first creating an alias
|
187
|
+
for the namespace for the class and then using the +element+ method on the Atom::Feed or Atom::Entry class to tell rAtom
|
188
|
+
to use your custom class when it encounters the extension element.
|
189
|
+
|
190
|
+
For example, say we have the following piece Atom XML with a structured extension element:
|
191
|
+
|
192
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
193
|
+
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:custom='http://custom.namespace'>
|
194
|
+
<id>https://custom.namespace/id/1</id>
|
195
|
+
<link rel='self' type='application/atom+xml' href='https://custom.namespace/id/1'/>
|
196
|
+
<custom:property name='foo' value='bar'/>
|
197
|
+
<custom:property name='baz' value='bat'/>
|
198
|
+
</entry>
|
199
|
+
|
200
|
+
And we want the +custom:property+ elements to be parsed as our own custom class called Custom::Property that is
|
201
|
+
defined like this:
|
202
|
+
|
203
|
+
class Custom::Property
|
204
|
+
attr_accessor :name, :value
|
205
|
+
def initialize(xml)
|
206
|
+
# Custom XML handling
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
We can tell rAtom about our custom namespace and custom class using the following method calls:
|
211
|
+
|
212
|
+
Atom::Feed..add_extension_namespace :custom, "http://custom.namespace"
|
213
|
+
Atom::Entry.elements "custom:property", :class => Custom::Property
|
214
|
+
|
215
|
+
The first method call registers an alias for the "http://custom.namespace" namespace and the second method call
|
216
|
+
tell rAtom that when it encounters a custom:property element within a Feed it should create an instance of Custom::Property
|
217
|
+
and pass the XML Reader to the constructor of the instance. It is then up to the constructor to populate the objects attributes
|
218
|
+
from the XML.
|
219
|
+
|
220
|
+
The custom property will then be available as a method on the rAtom class. In the above example:
|
221
|
+
|
222
|
+
@feed.custom_property.size == 2
|
223
|
+
@feed.custom_property.first.name == 'foo'
|
224
|
+
@feed.custom_property.first.value == 'bar'
|
225
|
+
|
226
|
+
(Thanks to nachokb for this feature!!)
|
227
|
+
|
184
228
|
=== Basic Authentication
|
185
229
|
|
186
230
|
All methods that involve HTTP requests now support HTTP Basic Authentication. Authentication credentials are passed
|
data/lib/atom/version.rb
CHANGED
data/lib/atom/xml/parser.rb
CHANGED
@@ -77,7 +77,7 @@ module Atom
|
|
77
77
|
loop do
|
78
78
|
case xml.node_type
|
79
79
|
when XML::Reader::TYPE_ELEMENT
|
80
|
-
if element_specs.include?(xml.local_name) && [Atom::NAMESPACE, Atom::Pub::NAMESPACE].include?(xml.namespace_uri)
|
80
|
+
if element_specs.include?(xml.local_name) && (self.class.known_namespaces + [Atom::NAMESPACE, Atom::Pub::NAMESPACE]).include?(xml.namespace_uri)
|
81
81
|
element_specs[xml.local_name].parse(self, xml)
|
82
82
|
elsif attributes.any?
|
83
83
|
while (xml.move_to_next_attribute == 1)
|
@@ -98,7 +98,9 @@ module Atom
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def next_node_is?(xml, element, ns = nil)
|
101
|
-
|
101
|
+
# Get to the next element
|
102
|
+
while xml.next == 1 && xml.node_type != XML::Reader::TYPE_ELEMENT; end
|
103
|
+
current_node_is?(xml, element, ns)
|
102
104
|
end
|
103
105
|
|
104
106
|
def current_node_is?(xml, element, ns = nil)
|
@@ -114,6 +116,9 @@ module Atom
|
|
114
116
|
def ordered_element_specs; self.class.ordered_element_specs; end
|
115
117
|
def attributes; self.class.attributes; end
|
116
118
|
def o.namespace(ns = @namespace); @namespace = ns; end
|
119
|
+
def o.add_extension_namespace(ns, url); self.extensions_namespaces[ns.to_s] = url; end
|
120
|
+
def o.extensions_namespaces; @extensions_namespaces ||= {} end
|
121
|
+
def o.known_namespaces; @known_namespaces ||= [] end
|
117
122
|
end
|
118
123
|
o.send(:extend, DeclarationMethods)
|
119
124
|
end
|
@@ -138,6 +143,9 @@ module Atom
|
|
138
143
|
namespace_map = NamespaceMap.new(self.class.namespace) if namespace_map.nil?
|
139
144
|
node = XML::Node.new(root_name)
|
140
145
|
node['xmlns'] = self.class.namespace unless nodeonly || !self.class.respond_to?(:namespace)
|
146
|
+
self.class.extensions_namespaces.each do |ns_alias,uri|
|
147
|
+
node["xmlns:#{ns_alias}"] = uri
|
148
|
+
end
|
141
149
|
|
142
150
|
self.class.ordered_element_specs.each do |spec|
|
143
151
|
if spec.single?
|
@@ -210,8 +218,10 @@ module Atom
|
|
210
218
|
options.merge!(names.pop) if names.last.is_a?(Hash)
|
211
219
|
|
212
220
|
names.each do |name|
|
213
|
-
attr_accessor name
|
214
|
-
|
221
|
+
attr_accessor name.to_s.sub(/:/, '_').to_sym
|
222
|
+
ns, local_name = name.to_s[/(.*):(.*)/,1], $2 || name
|
223
|
+
self.known_namespaces << self.extensions_namespaces[ns] if ns
|
224
|
+
self.ordered_element_specs << self.element_specs[local_name.to_s] = ParseSpec.new(name, options)
|
215
225
|
end
|
216
226
|
end
|
217
227
|
|
@@ -220,8 +230,16 @@ module Atom
|
|
220
230
|
options.merge!(names.pop) if names.last.is_a?(Hash)
|
221
231
|
|
222
232
|
names.each do |name|
|
223
|
-
|
224
|
-
|
233
|
+
name_sym = name.to_s.sub(/:/, '_').to_sym
|
234
|
+
attr_writer name_sym
|
235
|
+
define_method name_sym do
|
236
|
+
ivar = :"@#{name_sym}"
|
237
|
+
self.instance_variable_set ivar, [] unless self.instance_variable_defined? ivar
|
238
|
+
self.instance_variable_get ivar
|
239
|
+
end
|
240
|
+
ns, local_name = name.to_s[/(.*):(.*)/,1], $2 || name
|
241
|
+
self.known_namespaces << self.extensions_namespaces[ns] if ns
|
242
|
+
self.ordered_element_specs << self.element_specs[local_name.to_s.singularize] = ParseSpec.new(name, options)
|
225
243
|
end
|
226
244
|
end
|
227
245
|
|
@@ -314,7 +332,9 @@ module Atom
|
|
314
332
|
when :single
|
315
333
|
target.send("#{@attribute}=".to_sym, build(target, xml))
|
316
334
|
when :collection
|
317
|
-
target.send(
|
335
|
+
collection = target.send(@attribute.to_s)
|
336
|
+
element = build(target, xml)
|
337
|
+
collection << element
|
318
338
|
end
|
319
339
|
end
|
320
340
|
|
data/spec/atom_spec.rb
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
require File.dirname(__FILE__) + '/spec_helper.rb'
|
9
9
|
require 'net/http'
|
10
10
|
require 'time'
|
11
|
+
require 'spec/property'
|
11
12
|
|
12
13
|
shared_examples_for 'simple_single_entry.atom attributes' do
|
13
14
|
it "should parse title" do
|
@@ -183,6 +184,12 @@ describe Atom do
|
|
183
184
|
it_should_behave_like "simple_single_entry.atom attributes"
|
184
185
|
end
|
185
186
|
|
187
|
+
describe 'FeedWithStyleSheet' do
|
188
|
+
it "should load without failure" do
|
189
|
+
lambda { feed = Atom::Feed.load_feed(File.open('spec/fixtures/with_stylesheet.atom')) }.should_not raise_error
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
186
193
|
describe 'ComplexFeed' do
|
187
194
|
before(:all) do
|
188
195
|
@feed = Atom::Feed.load_feed(File.open('spec/fixtures/complex_single_entry.atom'))
|
@@ -1045,6 +1052,43 @@ describe Atom do
|
|
1045
1052
|
end
|
1046
1053
|
end
|
1047
1054
|
|
1055
|
+
describe 'custom_extensions' do
|
1056
|
+
before(:all) do
|
1057
|
+
Atom::Entry.add_extension_namespace :ns_alias, "http://custom.namespace"
|
1058
|
+
Atom::Entry.elements "ns_alias:property", :class => Atom::Extensions::Property
|
1059
|
+
@entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry_with_custom_extensions.atom'))
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
it "should_load_custom_extensions_for_entry" do
|
1063
|
+
@entry.ns_alias_property.should_not == []
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
it "should_load_2_custom_extensions_for_entry" do
|
1067
|
+
@entry.ns_alias_property.size.should == 2
|
1068
|
+
end
|
1069
|
+
|
1070
|
+
it "should load correct_data_for_custom_extensions_for_entry" do
|
1071
|
+
@entry.ns_alias_property.map { |x| [x.name, x.value] }.should == [['foo', 'bar'], ['baz', 'bat']]
|
1072
|
+
end
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
describe 'single custom_extensions' do
|
1076
|
+
before(:all) do
|
1077
|
+
Atom::Entry.add_extension_namespace :custom, "http://custom.namespace"
|
1078
|
+
Atom::Entry.element "custom:property", :class => Atom::Extensions::Property
|
1079
|
+
@entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry_with_single_custom_extension.atom'))
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
it "should load single custom extensions for entry" do
|
1083
|
+
@entry.custom_property.should_not be_nil
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
it "should load correct data for custom extensions for entry" do
|
1087
|
+
@entry.custom_property.name.should == 'foo'
|
1088
|
+
@entry.custom_property.value.should == 'bar'
|
1089
|
+
end
|
1090
|
+
end
|
1091
|
+
|
1048
1092
|
describe Atom::Link do
|
1049
1093
|
before(:each) do
|
1050
1094
|
@href = 'http://example.org/next'
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
2
|
+
<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>
|
3
|
+
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
|
4
|
+
<id>tag:blogger.com,1999:blog-3343849602113720282</id>
|
5
|
+
<updated>2008-07-26T09:01:19.322+01:00</updated>
|
6
|
+
<title type='text'>Blockstack.tv</title>
|
7
|
+
<link rel='alternate' type='text/html' href='http://blockstack.blogspot.com/'/>
|
8
|
+
</feed>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ratom
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peerworks
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2008-07-
|
13
|
+
date: 2008-07-28 00:00:00 +09:30
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -84,6 +84,7 @@ files:
|
|
84
84
|
- spec/fixtures/entry.atom
|
85
85
|
- spec/fixtures/multiple_entry.atom
|
86
86
|
- spec/fixtures/simple_single_entry.atom
|
87
|
+
- spec/fixtures/with_stylesheet.atom
|
87
88
|
- spec/paging/first_paged_feed.atom
|
88
89
|
- spec/paging/last_paged_feed.atom
|
89
90
|
- spec/paging/middle_paged_feed.atom
|