ealdent-sax-machine 0.0.7 → 0.0.12
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.
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:
|