pauldix-sax-machine 0.0.12 → 0.0.13
Sign up to get free protection for your applications and to get access to all the features.
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
|
|