ealdent-sax-machine 0.0.7 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
data/README.textile
CHANGED
@@ -48,6 +48,15 @@ feed.entries.first.title # => title of the first entry
|
|
48
48
|
feed.entries.first.author # => the author of the first entry
|
49
49
|
feed.entries.first.url # => the permalink on the blog for this entry
|
50
50
|
# etc ...
|
51
|
+
|
52
|
+
# you can also use the elements method without specifying a class like so
|
53
|
+
class SomeServiceResponse
|
54
|
+
elements :message, :as => :messages
|
55
|
+
end
|
56
|
+
|
57
|
+
response = SomeServiceResponse.parse("<response><message>hi</message><message>world</message></response>")
|
58
|
+
response.messages.first # => "hi"
|
59
|
+
response.messages.last # => "world"
|
51
60
|
</pre>
|
52
61
|
|
53
62
|
h2. LICENSE
|
data/lib/sax-machine.rb
CHANGED
@@ -21,10 +21,11 @@ module SAXMachine
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def element_config_for_attribute(name, attrs)
|
24
|
-
@top_level_elements.
|
24
|
+
element_configs = @top_level_elements.select do |element_config|
|
25
25
|
element_config.name == name &&
|
26
26
|
element_config.has_value_and_attrs_match?(attrs)
|
27
27
|
end
|
28
|
+
element_configs.empty? ? nil : element_configs
|
28
29
|
end
|
29
30
|
|
30
31
|
def element_config_for_tag(name, attrs)
|
@@ -23,19 +23,25 @@ module SAXMachine
|
|
23
23
|
options[:as] ||= name
|
24
24
|
sax_config.add_top_level_element(name, options)
|
25
25
|
|
26
|
-
# we only want to insert the setter if they haven't defined it from elsewhere.
|
26
|
+
# we only want to insert the getter and setter if they haven't defined it from elsewhere.
|
27
27
|
# this is how we allow custom parsing behavior. So you could define the setter
|
28
28
|
# and have it parse the string into a date or whatever.
|
29
|
-
|
30
|
-
|
31
|
-
else
|
32
|
-
attr_accessor options[:as]
|
33
|
-
end
|
29
|
+
attr_reader options[:as] unless instance_methods.include?(options[:as].to_s)
|
30
|
+
attr_writer options[:as] unless instance_methods.include?("#{options[:as]}=")
|
34
31
|
end
|
35
32
|
|
36
33
|
def elements(name, options = {})
|
37
34
|
options[:as] ||= name
|
38
|
-
|
35
|
+
if options[:class]
|
36
|
+
sax_config.add_collection_element(name, options)
|
37
|
+
else
|
38
|
+
class_eval <<-SRC
|
39
|
+
def add_#{options[:as]}(value)
|
40
|
+
#{options[:as]} << value
|
41
|
+
end
|
42
|
+
SRC
|
43
|
+
sax_config.add_top_level_element(name, options.merge(:collection => true))
|
44
|
+
end
|
39
45
|
|
40
46
|
class_eval <<-SRC
|
41
47
|
def #{options[:as]}
|
@@ -2,7 +2,7 @@ module SAXMachine
|
|
2
2
|
class SAXConfig
|
3
3
|
|
4
4
|
class ElementConfig
|
5
|
-
attr_reader :name
|
5
|
+
attr_reader :name, :setter
|
6
6
|
|
7
7
|
def initialize(name, options)
|
8
8
|
@name = name.to_s
|
@@ -21,16 +21,19 @@ module SAXMachine
|
|
21
21
|
end
|
22
22
|
|
23
23
|
@as = options[:as]
|
24
|
+
@collection = options[:collection]
|
25
|
+
|
26
|
+
if @collection
|
27
|
+
@setter = "add_#{options[:as]}"
|
28
|
+
else
|
29
|
+
@setter = "#{@as}="
|
30
|
+
end
|
24
31
|
end
|
25
32
|
|
26
33
|
def value_from_attrs(attrs)
|
27
34
|
attrs[attrs.index(@value) + 1]
|
28
35
|
end
|
29
36
|
|
30
|
-
def setter
|
31
|
-
"#{@as}="
|
32
|
-
end
|
33
|
-
|
34
37
|
def attrs_match?(attrs)
|
35
38
|
if @with
|
36
39
|
@with == (@with & attrs)
|
@@ -42,6 +45,10 @@ module SAXMachine
|
|
42
45
|
def has_value_and_attrs_match?(attrs)
|
43
46
|
!@value.nil? && attrs_match?(attrs)
|
44
47
|
end
|
48
|
+
|
49
|
+
def collection?
|
50
|
+
@collection
|
51
|
+
end
|
45
52
|
end
|
46
53
|
|
47
54
|
end
|
@@ -30,6 +30,7 @@ module SAXMachine
|
|
30
30
|
|
31
31
|
elsif @collection_config = sax_config.collection_config(@name)
|
32
32
|
@collection_handler = @collection_config.handler
|
33
|
+
@collection_handler.start_element(@name, @attrs)
|
33
34
|
|
34
35
|
elsif @element_config = sax_config.element_config_for_attribute(@name, @attrs)
|
35
36
|
parse_element_attribute
|
@@ -67,14 +68,18 @@ module SAXMachine
|
|
67
68
|
def parse_element_attribute
|
68
69
|
unless parsed_config?
|
69
70
|
mark_as_parsed
|
70
|
-
@
|
71
|
+
@element_config.each do |config|
|
72
|
+
@object.send(config.setter, config.value_from_attrs(@attrs))
|
73
|
+
end
|
71
74
|
end
|
72
75
|
|
73
76
|
@element_config = nil
|
74
77
|
end
|
75
78
|
|
76
79
|
def mark_as_parsed
|
77
|
-
|
80
|
+
# TODO: make this code not suck like this
|
81
|
+
@parsed_configs[@element_config] = true unless (@element_config.respond_to?(:collection?) && @element_config.collection?) ||
|
82
|
+
(@element_config.class == Array && @element_config.first.collection?)
|
78
83
|
end
|
79
84
|
|
80
85
|
def parsed_config?
|
@@ -209,37 +209,55 @@ describe "SAXMachine" do
|
|
209
209
|
document = @klass.parse("<link foo='test'/>")
|
210
210
|
document.link.should == 'test'
|
211
211
|
end
|
212
|
+
|
213
|
+
it "should save two different attribute values on a single tag" do
|
214
|
+
@klass = Class.new do
|
215
|
+
include SAXMachine
|
216
|
+
element :link, :value => :foo, :as => :first
|
217
|
+
element :link, :value => :bar, :as => :second
|
218
|
+
end
|
219
|
+
document = @klass.parse("<link foo='foo value' bar='bar value'></link>")
|
220
|
+
document.first.should == "foo value"
|
221
|
+
document.second.should == "bar value"
|
222
|
+
end
|
212
223
|
end
|
213
224
|
end
|
214
225
|
end
|
215
226
|
|
216
227
|
describe "elements" do
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
228
|
+
describe "when parsing multiple elements" do
|
229
|
+
before :each do
|
230
|
+
@klass = Class.new do
|
231
|
+
include SAXMachine
|
232
|
+
elements :entry, :as => :entries
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should provide a collection accessor" do
|
237
|
+
document = @klass.new
|
238
|
+
document.entries << :foo
|
239
|
+
document.entries.should == [:foo]
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should parse a single element" do
|
243
|
+
document = @klass.parse("<entry>hello</entry>")
|
244
|
+
document.entries.should == ["hello"]
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should parse multiple elements" do
|
248
|
+
document = @klass.parse("<xml><entry>hello</entry><entry>world</entry></xml>")
|
249
|
+
document.entries.should == ["hello", "world"]
|
250
|
+
end
|
251
|
+
|
252
|
+
it "should parse multiple elements when taking an attribute value" do
|
253
|
+
attribute_klass = Class.new do
|
254
|
+
include SAXMachine
|
255
|
+
elements :entry, :as => :entries, :value => :foo
|
256
|
+
end
|
257
|
+
doc = attribute_klass.parse("<xml><entry foo='asdf' /><entry foo='jkl' /></xml>")
|
258
|
+
doc.entries.should == ["asdf", "jkl"]
|
259
|
+
end
|
260
|
+
end
|
243
261
|
|
244
262
|
describe "when using the class option" do
|
245
263
|
before :each do
|
@@ -271,6 +289,16 @@ describe "SAXMachine" do
|
|
271
289
|
document.entries.size.should == 1
|
272
290
|
document.entries.first.title.should == "correct title"
|
273
291
|
end
|
292
|
+
|
293
|
+
it "should parse out an attribute value from the tag that starts the collection" do
|
294
|
+
class Foo
|
295
|
+
element :entry, :value => :href, :as => :url
|
296
|
+
end
|
297
|
+
document = @klass.parse("<xml><entry href='http://pauldix.net'><title>paul</title></entry></xml>")
|
298
|
+
document.entries.size.should == 1
|
299
|
+
document.entries.first.title.should == "paul"
|
300
|
+
document.entries.first.url.should == "http://pauldix.net"
|
301
|
+
end
|
274
302
|
end
|
275
303
|
end
|
276
304
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ealdent-sax-machine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Dix
|
@@ -14,6 +14,7 @@ default_executable:
|
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: nokogiri
|
17
|
+
type: :runtime
|
17
18
|
version_requirement:
|
18
19
|
version_requirements: !ruby/object:Gem::Requirement
|
19
20
|
requirements:
|