pauldix-sax-machine 0.0.12 → 0.0.13
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/lib/sax-machine.rb
CHANGED
@@ -7,33 +7,32 @@ module SAXMachine
|
|
7
7
|
@top_level_elements = []
|
8
8
|
@collection_elements = []
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def add_top_level_element(name, options)
|
12
12
|
@top_level_elements << ElementConfig.new(name, options)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def add_collection_element(name, options)
|
16
16
|
@collection_elements << CollectionConfig.new(name, options)
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def collection_config(name)
|
20
20
|
@collection_elements.detect { |ce| ce.name.to_s == name.to_s }
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
23
|
+
def element_configs_for_attribute(name, attrs)
|
24
|
+
@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
|
29
28
|
end
|
30
|
-
|
29
|
+
|
31
30
|
def element_config_for_tag(name, attrs)
|
32
31
|
@top_level_elements.detect do |element_config|
|
33
32
|
element_config.name == name &&
|
34
33
|
element_config.attrs_match?(attrs)
|
35
34
|
end
|
36
35
|
end
|
37
|
-
|
36
|
+
|
38
37
|
end
|
39
38
|
end
|
@@ -43,13 +43,15 @@ module SAXMachine
|
|
43
43
|
sax_config.add_top_level_element(name, options.merge(:collection => true))
|
44
44
|
end
|
45
45
|
|
46
|
+
if !instance_methods.include?(options[:as].to_s)
|
46
47
|
class_eval <<-SRC
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
def #{options[:as]}
|
49
|
+
@#{options[:as]} ||= []
|
50
|
+
end
|
51
|
+
SRC
|
52
|
+
end
|
51
53
|
|
52
|
-
attr_writer options[:as]
|
54
|
+
attr_writer options[:as] unless instance_methods.include?("#{options[:as]}=")
|
53
55
|
end
|
54
56
|
|
55
57
|
def sax_config
|
@@ -3,12 +3,12 @@ require "nokogiri"
|
|
3
3
|
module SAXMachine
|
4
4
|
class SAXHandler < Nokogiri::XML::SAX::Document
|
5
5
|
attr_reader :object
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(object)
|
8
8
|
@object = object
|
9
9
|
@parsed_configs = {}
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def characters(string)
|
13
13
|
if parsing_collection?
|
14
14
|
@collection_handler.characters(string)
|
@@ -16,88 +16,99 @@ module SAXMachine
|
|
16
16
|
@value << string
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def cdata_block(string)
|
21
21
|
characters(string)
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def start_element(name, attrs = [])
|
25
25
|
@name = name
|
26
26
|
@attrs = attrs
|
27
|
-
|
27
|
+
|
28
28
|
if parsing_collection?
|
29
29
|
@collection_handler.start_element(@name, @attrs)
|
30
|
-
|
30
|
+
|
31
31
|
elsif @collection_config = sax_config.collection_config(@name)
|
32
32
|
@collection_handler = @collection_config.handler
|
33
33
|
@collection_handler.start_element(@name, @attrs)
|
34
|
-
|
35
|
-
elsif
|
36
|
-
|
37
|
-
|
34
|
+
|
35
|
+
elsif (element_configs = sax_config.element_configs_for_attribute(@name, @attrs)).any?
|
36
|
+
parse_element_attributes(element_configs)
|
37
|
+
set_element_config_for_element_value
|
38
|
+
|
38
39
|
else
|
39
|
-
|
40
|
-
@element_config = sax_config.element_config_for_tag(@name, @attrs)
|
40
|
+
set_element_config_for_element_value
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def end_element(name)
|
45
45
|
if parsing_collection? && @collection_config.name == name
|
46
46
|
@object.send(@collection_config.accessor) << @collection_handler.object
|
47
47
|
reset_current_collection
|
48
|
-
|
48
|
+
|
49
49
|
elsif parsing_collection?
|
50
50
|
@collection_handler.end_element(name)
|
51
|
-
|
51
|
+
|
52
52
|
elsif characaters_captured? && !parsed_config?
|
53
53
|
mark_as_parsed
|
54
54
|
@object.send(@element_config.setter, @value)
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
reset_current_tag
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
def characaters_captured?
|
61
61
|
!@value.nil? && !@value.empty?
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
def parsing_collection?
|
65
65
|
!@collection_handler.nil?
|
66
66
|
end
|
67
|
-
|
68
|
-
def
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
67
|
+
|
68
|
+
def parse_collection_instance_attributes
|
69
|
+
instance = @collection_handler.object
|
70
|
+
@attrs.each_with_index do |attr_name,index|
|
71
|
+
instance.send("#{attr_name}=", @attrs[index + 1]) if index % 2 == 0 && instance.methods.include?("#{attr_name}=")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_element_attributes(element_configs)
|
76
|
+
element_configs.each do |ec|
|
77
|
+
unless parsed_config?(ec)
|
78
|
+
@object.send(ec.setter, ec.value_from_attrs(@attrs))
|
79
|
+
mark_as_parsed(ec)
|
73
80
|
end
|
74
81
|
end
|
75
|
-
|
76
82
|
@element_config = nil
|
77
83
|
end
|
78
|
-
|
79
|
-
def
|
80
|
-
|
81
|
-
@
|
82
|
-
(@element_config.class == Array && @element_config.first.collection?)
|
84
|
+
|
85
|
+
def set_element_config_for_element_value
|
86
|
+
@value = ""
|
87
|
+
@element_config = sax_config.element_config_for_tag(@name, @attrs)
|
83
88
|
end
|
84
|
-
|
85
|
-
def
|
86
|
-
@
|
89
|
+
|
90
|
+
def mark_as_parsed(element_config=nil)
|
91
|
+
element_config ||= @element_config
|
92
|
+
@parsed_configs[element_config] = true unless element_config.collection?
|
93
|
+
end
|
94
|
+
|
95
|
+
def parsed_config?(element_config=nil)
|
96
|
+
element_config ||= @element_config
|
97
|
+
@parsed_configs[element_config]
|
87
98
|
end
|
88
|
-
|
99
|
+
|
89
100
|
def reset_current_collection
|
90
101
|
@collection_handler = nil
|
91
102
|
@collection_config = nil
|
92
103
|
end
|
93
|
-
|
104
|
+
|
94
105
|
def reset_current_tag
|
95
106
|
@name = nil
|
96
107
|
@attrs = nil
|
97
108
|
@value = nil
|
98
109
|
@element_config = nil
|
99
110
|
end
|
100
|
-
|
111
|
+
|
101
112
|
def sax_config
|
102
113
|
@object.class.sax_config
|
103
114
|
end
|
@@ -220,7 +220,37 @@ describe "SAXMachine" do
|
|
220
220
|
document.first.should == "foo value"
|
221
221
|
document.second.should == "bar value"
|
222
222
|
end
|
223
|
+
|
224
|
+
it "should not fail if one of the attribute hasn't been defined" do
|
225
|
+
@klass = Class.new do
|
226
|
+
include SAXMachine
|
227
|
+
element :link, :value => :foo, :as => :first
|
228
|
+
element :link, :value => :bar, :as => :second
|
229
|
+
end
|
230
|
+
document = @klass.parse("<link foo='foo value'></link>")
|
231
|
+
document.first.should == "foo value"
|
232
|
+
document.second.should be_nil
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe "when desiring both the content and attributes of an element" do
|
237
|
+
before :each do
|
238
|
+
@klass = Class.new do
|
239
|
+
include SAXMachine
|
240
|
+
element :link
|
241
|
+
element :link, :value => :foo, :as => :link_foo
|
242
|
+
element :link, :value => :bar, :as => :link_bar
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should parse the element and attribute values" do
|
247
|
+
document = @klass.parse("<link foo='test1' bar='test2'>hello</link>")
|
248
|
+
document.link.should == 'hello'
|
249
|
+
document.link_foo.should == 'test1'
|
250
|
+
document.link_bar.should == 'test2'
|
251
|
+
end
|
223
252
|
end
|
253
|
+
|
224
254
|
end
|
225
255
|
end
|
226
256
|
|