sax-machine 0.2.1 → 0.3.0
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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.travis.yml +14 -4
- data/Gemfile +5 -1
- data/Guardfile +2 -2
- data/HISTORY.md +23 -6
- data/README.md +111 -40
- data/Rakefile +4 -3
- data/lib/sax-machine.rb +11 -2
- data/lib/sax-machine/{sax_ancestor_config.rb → config/sax_ancestor.rb} +3 -7
- data/lib/sax-machine/{sax_attribute_config.rb → config/sax_attribute.rb} +4 -6
- data/lib/sax-machine/{sax_collection_config.rb → config/sax_collection.rb} +6 -10
- data/lib/sax-machine/{sax_element_config.rb → config/sax_element.rb} +16 -17
- data/lib/sax-machine/{sax_element_value_config.rb → config/sax_element_value.rb} +5 -7
- data/lib/sax-machine/{sax_handler.rb → handlers/sax_abstract_handler.rb} +28 -32
- data/lib/sax-machine/handlers/sax_nokogiri_handler.rb +16 -0
- data/lib/sax-machine/handlers/sax_ox_handler.rb +41 -0
- data/lib/sax-machine/sax_config.rb +9 -9
- data/lib/sax-machine/sax_configure.rb +1 -6
- data/lib/sax-machine/sax_document.rb +28 -17
- data/lib/sax-machine/version.rb +2 -2
- data/sax-machine.gemspec +8 -11
- data/spec/fixtures/atom-content.html +15 -0
- data/spec/{sax-machine → fixtures}/atom.xml +0 -0
- data/spec/sax-machine/sax_activerecord_spec.rb +23 -0
- data/spec/sax-machine/sax_configure_spec.rb +48 -0
- data/spec/sax-machine/sax_document_spec.rb +333 -280
- data/spec/sax-machine/sax_include_spec.rb +43 -0
- data/spec/spec_helper.rb +11 -2
- metadata +36 -41
- data/spec/benchmarks/amazon.xml +0 -40
- data/spec/benchmarks/benchmark.rb +0 -158
- data/spec/benchmarks/public_timeline.xml +0 -411
- data/spec/sax-machine/configure_sax_machine_spec.rb +0 -53
- data/spec/sax-machine/include_sax_machine_spec.rb +0 -42
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
describe "ActiveRecord" do
|
5
|
+
describe "integration" do
|
6
|
+
before :each do
|
7
|
+
class MySaxModel < ActiveRecord::Base
|
8
|
+
SAXMachine.configure(MySaxModel) do |c|
|
9
|
+
c.element :title
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
after :each do
|
15
|
+
Object.send(:remove_const, :MySaxModel)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "parses document" do
|
19
|
+
document = MySaxModel.parse("<xml><title>My Title</title></xml>")
|
20
|
+
expect(document.title).to eq("My Title")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
class A
|
4
|
+
SAXMachine.configure(A) do |c|
|
5
|
+
c.element :title
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class B < A
|
10
|
+
SAXMachine.configure(B) do |c|
|
11
|
+
c.element :b
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class C < B
|
16
|
+
SAXMachine.configure(C) do |c|
|
17
|
+
c.element :c
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "SAXMachine configure" do
|
22
|
+
before do
|
23
|
+
xml = "<top><title>Test</title><b>Matched!</b><c>And Again</c></top>"
|
24
|
+
@a = A.new
|
25
|
+
@a.parse xml
|
26
|
+
@b = B.new
|
27
|
+
@b.parse xml
|
28
|
+
@c = C.new
|
29
|
+
@c.parse xml
|
30
|
+
end
|
31
|
+
|
32
|
+
it { expect(@a).to be_a(A) }
|
33
|
+
it { expect(@a).not_to be_a(B) }
|
34
|
+
it { expect(@a).to be_a(SAXMachine) }
|
35
|
+
it { expect(@a.title).to eq("Test") }
|
36
|
+
it { expect(@b).to be_a(A) }
|
37
|
+
it { expect(@b).to be_a(B) }
|
38
|
+
it { expect(@b).to be_a(SAXMachine) }
|
39
|
+
it { expect(@b.title).to eq("Test") }
|
40
|
+
it { expect(@b.b).to eq("Matched!") }
|
41
|
+
it { expect(@c).to be_a(A) }
|
42
|
+
it { expect(@c).to be_a(B) }
|
43
|
+
it { expect(@c).to be_a(C) }
|
44
|
+
it { expect(@c).to be_a(SAXMachine) }
|
45
|
+
it { expect(@c.title).to eq("Test") }
|
46
|
+
it { expect(@c.b).to eq("Matched!") }
|
47
|
+
it { expect(@c.c).to eq("And Again") }
|
48
|
+
end
|
@@ -10,22 +10,22 @@ describe "SAXMachine" do
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
it "
|
14
|
-
document = @klass.new(title:
|
15
|
-
document.title.
|
13
|
+
it "provides mass assignment through initialize method" do
|
14
|
+
document = @klass.new(title: "Title")
|
15
|
+
expect(document.title).to eq("Title")
|
16
16
|
end
|
17
17
|
|
18
|
-
it "
|
18
|
+
it "provides an accessor" do
|
19
19
|
document = @klass.new
|
20
20
|
document.title = "Title"
|
21
|
-
document.title.
|
21
|
+
expect(document.title).to eq("Title")
|
22
22
|
end
|
23
23
|
|
24
|
-
it "
|
25
|
-
@klass.column_names.
|
24
|
+
it "allows introspection of the elements" do
|
25
|
+
expect(@klass.column_names).to match_array([:title])
|
26
26
|
end
|
27
27
|
|
28
|
-
it "
|
28
|
+
it "does not overwrites the getter is there is already one present" do
|
29
29
|
@klass = Class.new do
|
30
30
|
def title
|
31
31
|
"#{@title} ***"
|
@@ -34,12 +34,13 @@ describe "SAXMachine" do
|
|
34
34
|
include SAXMachine
|
35
35
|
element :title
|
36
36
|
end
|
37
|
+
|
37
38
|
document = @klass.new
|
38
39
|
document.title = "Title"
|
39
|
-
document.title.
|
40
|
+
expect(document.title).to eq("Title ***")
|
40
41
|
end
|
41
42
|
|
42
|
-
it "
|
43
|
+
it "does not overwrites the setter if there is already one present" do
|
43
44
|
@klass = Class.new do
|
44
45
|
def title=(val)
|
45
46
|
@title = "#{val} **"
|
@@ -48,114 +49,119 @@ describe "SAXMachine" do
|
|
48
49
|
include SAXMachine
|
49
50
|
element :title
|
50
51
|
end
|
52
|
+
|
53
|
+
document = @klass.new
|
54
|
+
document.title = "Title"
|
55
|
+
expect(document.title).to eq("Title **")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "does not overwrites the accessor when the element is not present" do
|
51
59
|
document = @klass.new
|
52
60
|
document.title = "Title"
|
53
|
-
document.
|
61
|
+
document.parse("<foo></foo>")
|
62
|
+
expect(document.title).to eq("Title")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "overwrites the value when the element is present" do
|
66
|
+
document = @klass.new
|
67
|
+
document.title = "Old title"
|
68
|
+
document.parse("<title>New title</title>")
|
69
|
+
expect(document.title).to eq("New title")
|
70
|
+
end
|
71
|
+
|
72
|
+
it "saves the element text into an accessor" do
|
73
|
+
document = @klass.parse("<title>My Title</title>")
|
74
|
+
expect(document.title).to eq("My Title")
|
75
|
+
end
|
76
|
+
|
77
|
+
it "keeps the document encoding for elements" do
|
78
|
+
data = "<title>My Title</title>"
|
79
|
+
data.encode!("utf-8")
|
80
|
+
|
81
|
+
document = @klass.parse(data)
|
82
|
+
expect(document.title.encoding).to eq(data.encoding)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "saves cdata into an accessor" do
|
86
|
+
document = @klass.parse("<title><![CDATA[A Title]]></title>")
|
87
|
+
expect(document.title).to eq("A Title")
|
88
|
+
end
|
89
|
+
|
90
|
+
it "saves the element text into an accessor when there are multiple elements" do
|
91
|
+
document = @klass.parse("<xml><title>My Title</title><foo>bar</foo></xml>")
|
92
|
+
expect(document.title).to eq("My Title")
|
54
93
|
end
|
94
|
+
|
95
|
+
it "saves the first element text when there are multiple of the same element" do
|
96
|
+
document = @klass.parse("<xml><title>My Title</title><title>bar</title></xml>")
|
97
|
+
expect(document.title).to eq("My Title")
|
98
|
+
end
|
99
|
+
|
55
100
|
describe "the class attribute" do
|
56
101
|
before(:each) do
|
57
102
|
@klass = Class.new do
|
58
103
|
include SAXMachine
|
59
|
-
element :date, :
|
104
|
+
element :date, class: DateTime
|
60
105
|
end
|
106
|
+
|
61
107
|
@document = @klass.new
|
62
108
|
@document.date = Time.now.iso8601
|
63
109
|
end
|
64
|
-
|
65
|
-
|
110
|
+
|
111
|
+
it "is available" do
|
112
|
+
expect(@klass.data_class(:date)).to eq(DateTime)
|
66
113
|
end
|
67
|
-
|
68
|
-
it "
|
114
|
+
|
115
|
+
it "handles an integer class" do
|
69
116
|
@klass = Class.new do
|
70
117
|
include SAXMachine
|
71
|
-
element :number, :
|
118
|
+
element :number, class: Integer
|
72
119
|
end
|
120
|
+
|
73
121
|
document = @klass.parse("<number>5</number>")
|
74
|
-
document.number.
|
122
|
+
expect(document.number).to eq(5)
|
75
123
|
end
|
76
|
-
|
77
|
-
it "
|
124
|
+
|
125
|
+
it "handles an float class" do
|
78
126
|
@klass = Class.new do
|
79
127
|
include SAXMachine
|
80
|
-
element :number, :
|
128
|
+
element :number, class: Float
|
81
129
|
end
|
130
|
+
|
82
131
|
document = @klass.parse("<number>5.5</number>")
|
83
|
-
document.number.
|
84
|
-
end
|
132
|
+
expect(document.number).to eq(5.5)
|
133
|
+
end
|
85
134
|
|
86
|
-
it "
|
135
|
+
it "handles an string class" do
|
87
136
|
@klass = Class.new do
|
88
137
|
include SAXMachine
|
89
|
-
element :number, :
|
138
|
+
element :number, class: String
|
90
139
|
end
|
140
|
+
|
91
141
|
document = @klass.parse("<number>5.5</number>")
|
92
|
-
document.number.
|
142
|
+
expect(document.number).to eq("5.5")
|
93
143
|
end
|
94
|
-
|
95
|
-
it "
|
144
|
+
|
145
|
+
it "handles a time class" do
|
96
146
|
@klass = Class.new do
|
97
147
|
include SAXMachine
|
98
|
-
element :time, :
|
148
|
+
element :time, class: Time
|
99
149
|
end
|
150
|
+
|
100
151
|
document = @klass.parse("<time>1994-02-04T06:20:00Z</time>")
|
101
|
-
document.time.
|
152
|
+
expect(document.time).to eq(Time.utc(1994, 2, 4, 6, 20, 0, 0))
|
102
153
|
end
|
103
|
-
|
104
154
|
end
|
155
|
+
|
105
156
|
describe "the required attribute" do
|
106
|
-
it "
|
157
|
+
it "is available" do
|
107
158
|
@klass = Class.new do
|
108
159
|
include SAXMachine
|
109
|
-
element :date, :
|
160
|
+
element :date, required: true
|
110
161
|
end
|
111
|
-
@klass.required?(:date).
|
162
|
+
expect(@klass.required?(:date)).to be_truthy
|
112
163
|
end
|
113
164
|
end
|
114
|
-
|
115
|
-
it "should not overwrite the accessor when the element is not present" do
|
116
|
-
document = @klass.new
|
117
|
-
document.title = "Title"
|
118
|
-
document.parse("<foo></foo>")
|
119
|
-
document.title.should == "Title"
|
120
|
-
end
|
121
|
-
|
122
|
-
it "should overwrite the value when the element is present" do
|
123
|
-
document = @klass.new
|
124
|
-
document.title = "Old title"
|
125
|
-
document.parse("<title>New title</title>")
|
126
|
-
document.title.should == "New title"
|
127
|
-
end
|
128
|
-
|
129
|
-
it "should save the element text into an accessor" do
|
130
|
-
document = @klass.parse("<title>My Title</title>")
|
131
|
-
document.title.should == "My Title"
|
132
|
-
end
|
133
|
-
|
134
|
-
if RUBY_VERSION >= "1.9.0"
|
135
|
-
it "should keep the document encoding for elements" do
|
136
|
-
data = "<title>My Title</title>"
|
137
|
-
data.encode!("utf-8")
|
138
|
-
|
139
|
-
document = @klass.parse(data)
|
140
|
-
document.title.encoding.should == data.encoding
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
it "should save cdata into an accessor" do
|
145
|
-
document = @klass.parse("<title><![CDATA[A Title]]></title>")
|
146
|
-
document.title.should == "A Title"
|
147
|
-
end
|
148
|
-
|
149
|
-
it "should save the element text into an accessor when there are multiple elements" do
|
150
|
-
document = @klass.parse("<xml><title>My Title</title><foo>bar</foo></xml>")
|
151
|
-
document.title.should == "My Title"
|
152
|
-
end
|
153
|
-
|
154
|
-
it "should save the first element text when there are multiple of the same element" do
|
155
|
-
document = @klass.parse("<xml><title>My Title</title><title>bar</title></xml>")
|
156
|
-
document.title.should == "My Title"
|
157
|
-
|
158
|
-
end
|
159
165
|
end
|
160
166
|
|
161
167
|
describe "when parsing multiple elements" do
|
@@ -167,14 +173,13 @@ describe "SAXMachine" do
|
|
167
173
|
end
|
168
174
|
end
|
169
175
|
|
170
|
-
it "
|
176
|
+
it "saves the element text for a second tag" do
|
171
177
|
document = @klass.parse("<xml><title>My Title</title><name>Paul</name></xml>")
|
172
|
-
document.name.
|
173
|
-
document.title.
|
178
|
+
expect(document.name).to eq("Paul")
|
179
|
+
expect(document.title).to eq("My Title")
|
174
180
|
end
|
175
181
|
|
176
|
-
|
177
|
-
it "should not overwrite the getter is there is already one present" do
|
182
|
+
it "does not overwrites the getter is there is already one present" do
|
178
183
|
@klass = Class.new do
|
179
184
|
def items
|
180
185
|
[]
|
@@ -183,12 +188,13 @@ describe "SAXMachine" do
|
|
183
188
|
include SAXMachine
|
184
189
|
elements :items
|
185
190
|
end
|
191
|
+
|
186
192
|
document = @klass.new
|
187
193
|
document.items = [1, 2, 3, 4]
|
188
|
-
document.items.
|
194
|
+
expect(document.items).to eq([])
|
189
195
|
end
|
190
196
|
|
191
|
-
it "
|
197
|
+
it "does not overwrites the setter if there is already one present" do
|
192
198
|
@klass = Class.new do
|
193
199
|
def items=(val)
|
194
200
|
@items = [1, *val]
|
@@ -197,11 +203,11 @@ describe "SAXMachine" do
|
|
197
203
|
include SAXMachine
|
198
204
|
elements :items
|
199
205
|
end
|
206
|
+
|
200
207
|
document = @klass.new
|
201
208
|
document.items = [2, 3]
|
202
|
-
document.items.
|
209
|
+
expect(document.items).to eq([1, 2, 3])
|
203
210
|
end
|
204
|
-
|
205
211
|
end
|
206
212
|
|
207
213
|
describe "when using options for parsing elements" do
|
@@ -209,19 +215,19 @@ describe "SAXMachine" do
|
|
209
215
|
before :each do
|
210
216
|
@klass = Class.new do
|
211
217
|
include SAXMachine
|
212
|
-
element :description, :
|
218
|
+
element :description, as: :summary
|
213
219
|
end
|
214
220
|
end
|
215
221
|
|
216
|
-
it "
|
222
|
+
it "provides an accessor using the 'as' name" do
|
217
223
|
document = @klass.new
|
218
224
|
document.summary = "a small summary"
|
219
|
-
document.summary.
|
225
|
+
expect(document.summary).to eq("a small summary")
|
220
226
|
end
|
221
227
|
|
222
|
-
it "
|
228
|
+
it "saves the element text into the 'as' accessor" do
|
223
229
|
document = @klass.parse("<description>here is a description</description>")
|
224
|
-
document.summary.
|
230
|
+
expect(document.summary).to eq("here is a description")
|
225
231
|
end
|
226
232
|
end
|
227
233
|
|
@@ -230,35 +236,34 @@ describe "SAXMachine" do
|
|
230
236
|
before :each do
|
231
237
|
@klass = Class.new do
|
232
238
|
include SAXMachine
|
233
|
-
element :link, :
|
239
|
+
element :link, value: :href, with: { foo: "bar" }
|
234
240
|
end
|
235
241
|
end
|
236
242
|
|
237
|
-
it "
|
243
|
+
it "saves the value of a matching element" do
|
238
244
|
document = @klass.parse("<link href='test' foo='bar'>asdf</link>")
|
239
|
-
document.link.
|
245
|
+
expect(document.link).to eq("test")
|
240
246
|
end
|
241
247
|
|
242
|
-
it "
|
248
|
+
it "saves the value of the first matching element" do
|
243
249
|
document = @klass.parse("<xml><link href='first' foo='bar' /><link href='second' foo='bar' /></xml>")
|
244
|
-
document.link.
|
250
|
+
expect(document.link).to eq("first")
|
245
251
|
end
|
246
252
|
|
247
253
|
describe "and the :as option" do
|
248
254
|
before :each do
|
249
255
|
@klass = Class.new do
|
250
256
|
include SAXMachine
|
251
|
-
element :link, :
|
252
|
-
element :link, :
|
257
|
+
element :link, value: :href, as: :url, with: { foo: "bar" }
|
258
|
+
element :link, value: :href, as: :second_url, with: { asdf: "jkl" }
|
253
259
|
end
|
254
260
|
end
|
255
261
|
|
256
|
-
it "
|
262
|
+
it "saves the value of the first matching element" do
|
257
263
|
document = @klass.parse("<xml><link href='first' foo='bar' /><link href='second' asdf='jkl' /><link href='second' foo='bar' /></xml>")
|
258
|
-
document.url.
|
259
|
-
document.second_url.
|
264
|
+
expect(document.url).to eq("first")
|
265
|
+
expect(document.second_url).to eq("second")
|
260
266
|
end
|
261
|
-
|
262
267
|
end
|
263
268
|
end
|
264
269
|
|
@@ -266,29 +271,28 @@ describe "SAXMachine" do
|
|
266
271
|
before :each do
|
267
272
|
@klass = Class.new do
|
268
273
|
include SAXMachine
|
269
|
-
element :link, :
|
274
|
+
element :link, with: { foo: "bar" }
|
270
275
|
end
|
271
276
|
end
|
272
277
|
|
273
|
-
it "
|
278
|
+
it "saves the text of an element that has matching attributes" do
|
274
279
|
document = @klass.parse("<link foo=\"bar\">match</link>")
|
275
|
-
document.link.
|
280
|
+
expect(document.link).to eq("match")
|
276
281
|
end
|
277
282
|
|
278
|
-
it "
|
283
|
+
it "does not saves the text of an element that doesn't have matching attributes" do
|
279
284
|
document = @klass.parse("<link>no match</link>")
|
280
|
-
document.link.
|
285
|
+
expect(document.link).to be_nil
|
281
286
|
end
|
282
287
|
|
283
|
-
it "
|
288
|
+
it "saves the text of an element that has matching attributes when it is the second of that type" do
|
284
289
|
document = @klass.parse("<xml><link>no match</link><link foo=\"bar\">match</link></xml>")
|
285
|
-
document.link.
|
286
|
-
|
290
|
+
expect(document.link).to eq("match")
|
287
291
|
end
|
288
292
|
|
289
|
-
it "
|
293
|
+
it "saves the text of an element that has matching attributes plus a few more" do
|
290
294
|
document = @klass.parse("<xml><link>no match</link><link asdf='jkl' foo='bar'>match</link>")
|
291
|
-
document.link.
|
295
|
+
expect(document.link).to eq("match")
|
292
296
|
end
|
293
297
|
end
|
294
298
|
|
@@ -296,19 +300,19 @@ describe "SAXMachine" do
|
|
296
300
|
before :each do
|
297
301
|
@klass = Class.new do
|
298
302
|
include SAXMachine
|
299
|
-
element :link, :
|
300
|
-
element :link, :
|
303
|
+
element :link, as: :first, with: { foo: "bar" }
|
304
|
+
element :link, as: :second, with: { asdf: "jkl" }
|
301
305
|
end
|
302
306
|
end
|
303
307
|
|
304
|
-
it "
|
308
|
+
it "matches the first element" do
|
305
309
|
document = @klass.parse("<xml><link>no match</link><link foo=\"bar\">first match</link><link>no match</link></xml>")
|
306
|
-
document.first.
|
310
|
+
expect(document.first).to eq("first match")
|
307
311
|
end
|
308
312
|
|
309
|
-
it "
|
313
|
+
it "matches the second element" do
|
310
314
|
document = @klass.parse("<xml><link>no match</link><link foo='bar'>first match</link><link asdf='jkl'>second match</link><link>hi</link></xml>")
|
311
|
-
document.second.
|
315
|
+
expect(document.second).to eq("second match")
|
312
316
|
end
|
313
317
|
end
|
314
318
|
|
@@ -316,75 +320,77 @@ describe "SAXMachine" do
|
|
316
320
|
before :each do
|
317
321
|
@klass = Class.new do
|
318
322
|
include SAXMachine
|
319
|
-
element :link, :
|
323
|
+
element :link, with: { foo: /ar$/ }
|
320
324
|
end
|
321
325
|
end
|
322
326
|
|
323
|
-
it "
|
327
|
+
it "saves the text of an element that has matching attributes" do
|
324
328
|
document = @klass.parse("<link foo=\"bar\">match</link>")
|
325
|
-
document.link.
|
329
|
+
expect(document.link).to eq("match")
|
326
330
|
end
|
327
331
|
|
328
|
-
it "
|
332
|
+
it "does not saves the text of an element that doesn't have matching attributes" do
|
329
333
|
document = @klass.parse("<link>no match</link>")
|
330
|
-
document.link.
|
334
|
+
expect(document.link).to be_nil
|
331
335
|
end
|
332
336
|
|
333
|
-
it "
|
337
|
+
it "saves the text of an element that has matching attributes when it is the second of that type" do
|
334
338
|
document = @klass.parse("<xml><link>no match</link><link foo=\"bar\">match</link></xml>")
|
335
|
-
document.link.
|
339
|
+
expect(document.link).to eq("match")
|
336
340
|
end
|
337
341
|
|
338
|
-
it "
|
342
|
+
it "saves the text of an element that has matching attributes plus a few more" do
|
339
343
|
document = @klass.parse("<xml><link>no match</link><link asdf='jkl' foo='bar'>match</link>")
|
340
|
-
document.link.
|
344
|
+
expect(document.link).to eq("match")
|
341
345
|
end
|
342
346
|
end
|
343
|
-
end
|
347
|
+
end
|
344
348
|
|
345
349
|
describe "using the 'value' option" do
|
346
350
|
before :each do
|
347
351
|
@klass = Class.new do
|
348
352
|
include SAXMachine
|
349
|
-
element :link, :
|
353
|
+
element :link, value: :foo
|
350
354
|
end
|
351
355
|
end
|
352
356
|
|
353
|
-
it "
|
357
|
+
it "saves the attribute value" do
|
354
358
|
document = @klass.parse("<link foo='test'>hello</link>")
|
355
|
-
document.link.
|
359
|
+
expect(document.link).to eq("test")
|
356
360
|
end
|
357
361
|
|
358
|
-
it "
|
362
|
+
it "saves the attribute value when there is no text enclosed by the tag" do
|
359
363
|
document = @klass.parse("<link foo='test'></link>")
|
360
|
-
document.link.
|
364
|
+
expect(document.link).to eq("test")
|
361
365
|
end
|
362
366
|
|
363
|
-
it "
|
367
|
+
it "saves the attribute value when the tag close is in the open" do
|
364
368
|
document = @klass.parse("<link foo='test'/>")
|
365
|
-
document.link.
|
369
|
+
expect(document.link).to eq("test")
|
366
370
|
end
|
367
371
|
|
368
|
-
it "
|
372
|
+
it "saves two different attribute values on a single tag" do
|
369
373
|
@klass = Class.new do
|
370
374
|
include SAXMachine
|
371
|
-
element :link, :
|
372
|
-
element :link, :
|
375
|
+
element :link, value: :foo, as: :first
|
376
|
+
element :link, value: :bar, as: :second
|
373
377
|
end
|
378
|
+
|
374
379
|
document = @klass.parse("<link foo='foo value' bar='bar value'></link>")
|
375
|
-
document.first.
|
376
|
-
document.second.
|
380
|
+
expect(document.first).to eq("foo value")
|
381
|
+
expect(document.second).to eq("bar value")
|
377
382
|
end
|
378
383
|
|
379
|
-
it "
|
384
|
+
it "does not fail if one of the attribute hasn't been defined" do
|
380
385
|
@klass = Class.new do
|
381
386
|
include SAXMachine
|
382
|
-
element :link, :
|
383
|
-
element :link, :
|
387
|
+
element :link, value: :foo, as: :first
|
388
|
+
element :link, value: :bar, as: :second
|
384
389
|
end
|
390
|
+
|
385
391
|
document = @klass.parse("<link foo='foo value'></link>")
|
386
|
-
document.first.
|
387
|
-
document.second.
|
392
|
+
expect(document.first).to eq("foo value")
|
393
|
+
expect(document.second).to be_nil
|
388
394
|
end
|
389
395
|
end
|
390
396
|
|
@@ -393,19 +399,18 @@ describe "SAXMachine" do
|
|
393
399
|
@klass = Class.new do
|
394
400
|
include SAXMachine
|
395
401
|
element :link
|
396
|
-
element :link, :
|
397
|
-
element :link, :
|
402
|
+
element :link, value: :foo, as: :link_foo
|
403
|
+
element :link, value: :bar, as: :link_bar
|
398
404
|
end
|
399
405
|
end
|
400
406
|
|
401
|
-
it "
|
407
|
+
it "parses the element and attribute values" do
|
402
408
|
document = @klass.parse("<link foo='test1' bar='test2'>hello</link>")
|
403
|
-
document.link.
|
404
|
-
document.link_foo.
|
405
|
-
document.link_bar.
|
409
|
+
expect(document.link).to eq("hello")
|
410
|
+
expect(document.link_foo).to eq("test1")
|
411
|
+
expect(document.link_bar).to eq("test2")
|
406
412
|
end
|
407
413
|
end
|
408
|
-
|
409
414
|
end
|
410
415
|
end
|
411
416
|
|
@@ -414,33 +419,34 @@ describe "SAXMachine" do
|
|
414
419
|
before :each do
|
415
420
|
@klass = Class.new do
|
416
421
|
include SAXMachine
|
417
|
-
elements :entry, :
|
422
|
+
elements :entry, as: :entries
|
418
423
|
end
|
419
424
|
end
|
420
425
|
|
421
|
-
it "
|
426
|
+
it "provides a collection accessor" do
|
422
427
|
document = @klass.new
|
423
428
|
document.entries << :foo
|
424
|
-
document.entries.
|
429
|
+
expect(document.entries).to eq([:foo])
|
425
430
|
end
|
426
431
|
|
427
|
-
it "
|
432
|
+
it "parses a single element" do
|
428
433
|
document = @klass.parse("<entry>hello</entry>")
|
429
|
-
document.entries.
|
434
|
+
expect(document.entries).to eq(["hello"])
|
430
435
|
end
|
431
436
|
|
432
|
-
it "
|
437
|
+
it "parses multiple elements" do
|
433
438
|
document = @klass.parse("<xml><entry>hello</entry><entry>world</entry></xml>")
|
434
|
-
document.entries.
|
439
|
+
expect(document.entries).to eq(["hello", "world"])
|
435
440
|
end
|
436
441
|
|
437
|
-
it "
|
442
|
+
it "parses multiple elements when taking an attribute value" do
|
438
443
|
attribute_klass = Class.new do
|
439
444
|
include SAXMachine
|
440
|
-
elements :entry, :
|
445
|
+
elements :entry, as: :entries, value: :foo
|
441
446
|
end
|
447
|
+
|
442
448
|
doc = attribute_klass.parse("<xml><entry foo='asdf' /><entry foo='jkl' /></xml>")
|
443
|
-
doc.entries.
|
449
|
+
expect(doc.entries).to eq(["asdf", "jkl"])
|
444
450
|
end
|
445
451
|
end
|
446
452
|
|
@@ -458,22 +464,22 @@ describe "SAXMachine" do
|
|
458
464
|
|
459
465
|
class Item
|
460
466
|
include SAXMachine
|
461
|
-
|
462
467
|
end
|
468
|
+
|
463
469
|
@klass = Class.new do
|
464
470
|
include SAXMachine
|
465
|
-
elements :item, :
|
466
|
-
elements :item, :
|
471
|
+
elements :item, as: :items, with: { type: "Bar" }, class: Bar
|
472
|
+
elements :item, as: :items, with: { type: /Foo/ }, class: Foo
|
467
473
|
end
|
468
474
|
end
|
469
|
-
|
470
|
-
it "
|
475
|
+
|
476
|
+
it "casts into the correct class" do
|
471
477
|
document = @klass.parse("<items><item type=\"Bar\"><title>Bar title</title></item><item type=\"Foo\"><title>Foo title</title></item></items>")
|
472
|
-
document.items.size.
|
473
|
-
document.items.first.
|
474
|
-
document.items.first.title.
|
475
|
-
document.items.last.
|
476
|
-
document.items.last.title.
|
478
|
+
expect(document.items.size).to eq(2)
|
479
|
+
expect(document.items.first).to be_a(Bar)
|
480
|
+
expect(document.items.first.title).to eq("Bar title")
|
481
|
+
expect(document.items.last).to be_a(Foo)
|
482
|
+
expect(document.items.last.title).to eq("Foo title")
|
477
483
|
end
|
478
484
|
end
|
479
485
|
|
@@ -483,81 +489,85 @@ describe "SAXMachine" do
|
|
483
489
|
include SAXMachine
|
484
490
|
element :title
|
485
491
|
end
|
492
|
+
|
486
493
|
@klass = Class.new do
|
487
494
|
include SAXMachine
|
488
|
-
elements :entry, :
|
495
|
+
elements :entry, as: :entries, class: Foo
|
489
496
|
end
|
490
497
|
end
|
491
498
|
|
492
|
-
it "
|
499
|
+
it "parses a single element with children" do
|
493
500
|
document = @klass.parse("<entry><title>a title</title></entry>")
|
494
|
-
document.entries.size.
|
495
|
-
document.entries.first.title.
|
501
|
+
expect(document.entries.size).to eq(1)
|
502
|
+
expect(document.entries.first.title).to eq("a title")
|
496
503
|
end
|
497
504
|
|
498
|
-
it "
|
505
|
+
it "parses multiple elements with children" do
|
499
506
|
document = @klass.parse("<xml><entry><title>title 1</title></entry><entry><title>title 2</title></entry></xml>")
|
500
|
-
document.entries.size.
|
501
|
-
document.entries.first.title.
|
502
|
-
document.entries.last.title.
|
507
|
+
expect(document.entries.size).to eq(2)
|
508
|
+
expect(document.entries.first.title).to eq("title 1")
|
509
|
+
expect(document.entries.last.title).to eq("title 2")
|
503
510
|
end
|
504
511
|
|
505
|
-
it "
|
512
|
+
it "does not parse a top level element that is specified only in a child" do
|
506
513
|
document = @klass.parse("<xml><title>no parse</title><entry><title>correct title</title></entry></xml>")
|
507
|
-
document.entries.size.
|
508
|
-
document.entries.first.title.
|
514
|
+
expect(document.entries.size).to eq(1)
|
515
|
+
expect(document.entries.first.title).to eq("correct title")
|
509
516
|
end
|
510
517
|
|
511
|
-
it "
|
518
|
+
it "parses elements, and make attributes and inner text available" do
|
512
519
|
class Related
|
513
520
|
include SAXMachine
|
514
|
-
element
|
515
|
-
element
|
521
|
+
element "related", as: :item
|
522
|
+
element "related", as: :attr, value: "attr"
|
516
523
|
end
|
524
|
+
|
517
525
|
class Foo
|
518
|
-
elements
|
526
|
+
elements "related", as: "items", class: Related
|
519
527
|
end
|
520
528
|
|
521
529
|
doc = Foo.parse(%{<xml><collection><related attr='baz'>something</related><related>somethingelse</related></collection></xml>})
|
522
|
-
doc.items.first.
|
523
|
-
doc.items.size.
|
524
|
-
doc.items.first.item.
|
525
|
-
doc.items.last.item.
|
530
|
+
expect(doc.items.first).not_to be_nil
|
531
|
+
expect(doc.items.size).to eq(2)
|
532
|
+
expect(doc.items.first.item).to eq("something")
|
533
|
+
expect(doc.items.last.item).to eq("somethingelse")
|
526
534
|
end
|
527
535
|
|
528
|
-
it "
|
536
|
+
it "parses out an attribute value from the tag that starts the collection" do
|
529
537
|
class Foo
|
530
|
-
element :entry, :
|
538
|
+
element :entry, value: :href, as: :url
|
531
539
|
end
|
540
|
+
|
532
541
|
document = @klass.parse("<xml><entry href='http://pauldix.net'><title>paul</title></entry></xml>")
|
533
|
-
document.entries.size.
|
534
|
-
document.entries.first.title.
|
535
|
-
document.entries.first.url.
|
542
|
+
expect(document.entries.size).to eq(1)
|
543
|
+
expect(document.entries.first.title).to eq("paul")
|
544
|
+
expect(document.entries.first.url).to eq("http://pauldix.net")
|
536
545
|
end
|
537
546
|
end
|
538
547
|
end
|
539
|
-
|
548
|
+
|
540
549
|
describe "when dealing with element names containing dashes" do
|
541
|
-
it
|
550
|
+
it "converts dashes to underscores" do
|
542
551
|
class Dashes
|
543
552
|
include SAXMachine
|
544
553
|
element :dashed_element
|
545
554
|
end
|
546
|
-
|
547
|
-
parsed = Dashes.parse(
|
548
|
-
parsed.dashed_element.
|
555
|
+
|
556
|
+
parsed = Dashes.parse("<dashed-element>Text</dashed-element>")
|
557
|
+
expect(parsed.dashed_element).to eq "Text"
|
549
558
|
end
|
550
559
|
end
|
551
560
|
|
552
561
|
describe "full example" do
|
553
562
|
before :each do
|
554
|
-
@xml = File.read(
|
563
|
+
@xml = File.read("spec/fixtures/atom.xml")
|
564
|
+
|
555
565
|
class AtomEntry
|
556
566
|
include SAXMachine
|
557
567
|
element :title
|
558
|
-
element :name, :
|
559
|
-
element "feedburner:origLink", :
|
560
|
-
element :link, :
|
568
|
+
element :name, as: :author
|
569
|
+
element "feedburner:origLink", as: :url
|
570
|
+
element :link, as: :alternate, value: :href, with: { type: "text/html", rel: "alternate" }
|
561
571
|
element :summary
|
562
572
|
element :content
|
563
573
|
element :published
|
@@ -566,21 +576,25 @@ describe "SAXMachine" do
|
|
566
576
|
class Atom
|
567
577
|
include SAXMachine
|
568
578
|
element :title
|
569
|
-
element :link, :
|
570
|
-
element :link, :
|
571
|
-
elements :entry, :
|
579
|
+
element :link, value: :href, as: :url, with: { type: "text/html" }
|
580
|
+
element :link, value: :href, as: :feed_url, with: { type: "application/atom+xml" }
|
581
|
+
elements :entry, as: :entries, class: AtomEntry
|
572
582
|
end
|
573
|
-
end # before
|
574
583
|
|
575
|
-
|
576
|
-
|
577
|
-
|
584
|
+
@feed = Atom.parse(@xml)
|
585
|
+
end
|
586
|
+
|
587
|
+
it "parses the url" do
|
588
|
+
expect(@feed.url).to eq("http://www.pauldix.net/")
|
589
|
+
end
|
590
|
+
|
591
|
+
it "parses entry url" do
|
592
|
+
expect(@feed.entries.first.url).to eq("http://www.pauldix.net/2008/09/marshal-data-to.html?param1=1¶m2=2")
|
593
|
+
expect(@feed.entries.first.alternate).to eq("http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~3/383536354/marshal-data-to.html?param1=1¶m2=2")
|
578
594
|
end
|
579
595
|
|
580
|
-
it "
|
581
|
-
|
582
|
-
f.entries.first.url.should == "http://www.pauldix.net/2008/09/marshal-data-to.html?param1=1¶m2=2"
|
583
|
-
f.entries.first.alternate.should == "http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~3/383536354/marshal-data-to.html?param1=1¶m2=2"
|
596
|
+
it "parses content" do
|
597
|
+
expect(@feed.entries.first.content).to eq(File.read("spec/fixtures/atom-content.html"))
|
584
598
|
end
|
585
599
|
end
|
586
600
|
|
@@ -598,32 +612,35 @@ describe "SAXMachine" do
|
|
598
612
|
</category>
|
599
613
|
</categories>
|
600
614
|
]
|
601
|
-
|
602
|
-
end
|
615
|
+
|
616
|
+
class CategoryCollection; end
|
617
|
+
|
603
618
|
class Category
|
604
619
|
include SAXMachine
|
605
620
|
attr_accessor :id
|
606
|
-
element :category, :
|
621
|
+
element :category, value: :id, as: :id
|
607
622
|
element :title
|
608
|
-
element :categories, :
|
623
|
+
element :categories, as: :collection, class: CategoryCollection
|
609
624
|
ancestor :ancestor
|
610
625
|
end
|
626
|
+
|
611
627
|
class CategoryCollection
|
612
628
|
include SAXMachine
|
613
|
-
elements :category, :
|
629
|
+
elements :category, as: :categories, class: Category
|
614
630
|
end
|
631
|
+
|
615
632
|
@collection = CategoryCollection.parse(@xml)
|
616
633
|
end
|
617
634
|
|
618
|
-
it "
|
619
|
-
@collection.categories.first.id.
|
620
|
-
@collection.categories.first.title.
|
621
|
-
@collection.categories.first.ancestor.
|
635
|
+
it "parses the first category" do
|
636
|
+
expect(@collection.categories.first.id).to eq("1")
|
637
|
+
expect(@collection.categories.first.title).to eq("First")
|
638
|
+
expect(@collection.categories.first.ancestor).to eq(@collection)
|
622
639
|
end
|
623
640
|
|
624
|
-
it "
|
625
|
-
@collection.categories.first.collection.categories.first.id.
|
626
|
-
@collection.categories.first.collection.categories.first.title.
|
641
|
+
it "parses the nested category" do
|
642
|
+
expect(@collection.categories.first.collection.categories.first.id).to eq("2")
|
643
|
+
expect(@collection.categories.first.collection.categories.first.title).to eq("Second")
|
627
644
|
end
|
628
645
|
end
|
629
646
|
|
@@ -641,24 +658,26 @@ describe "SAXMachine" do
|
|
641
658
|
</category>
|
642
659
|
</categories>
|
643
660
|
]
|
661
|
+
|
644
662
|
class CategoryTree
|
645
663
|
include SAXMachine
|
646
664
|
attr_accessor :id
|
647
|
-
element :category, :
|
665
|
+
element :category, value: :id, as: :id
|
648
666
|
element :title
|
649
|
-
elements :category, :
|
667
|
+
elements :category, as: :categories, class: CategoryTree
|
650
668
|
end
|
669
|
+
|
651
670
|
@collection = CategoryTree.parse(@xml)
|
652
671
|
end
|
653
672
|
|
654
|
-
it "
|
655
|
-
@collection.categories.first.id.
|
656
|
-
@collection.categories.first.title.
|
673
|
+
it "parses the first category" do
|
674
|
+
expect(@collection.categories.first.id).to eq("1")
|
675
|
+
expect(@collection.categories.first.title).to eq("First")
|
657
676
|
end
|
658
677
|
|
659
|
-
it "
|
660
|
-
@collection.categories.first.categories.first.id.
|
661
|
-
@collection.categories.first.categories.first.title.
|
678
|
+
it "parses the nested category" do
|
679
|
+
expect(@collection.categories.first.categories.first.id).to eq("2")
|
680
|
+
expect(@collection.categories.first.categories.first.title).to eq("Second")
|
662
681
|
end
|
663
682
|
end
|
664
683
|
|
@@ -671,21 +690,23 @@ describe "SAXMachine" do
|
|
671
690
|
</texts>
|
672
691
|
</item>
|
673
692
|
]
|
693
|
+
|
674
694
|
@klass = Class.new do
|
675
695
|
include SAXMachine
|
676
696
|
attr_accessor :id
|
677
|
-
element :item, :
|
697
|
+
element :item, value: "id", as: :id
|
678
698
|
element :title
|
679
699
|
end
|
700
|
+
|
680
701
|
@item = @klass.parse(@xml)
|
681
702
|
end
|
682
703
|
|
683
|
-
it "
|
684
|
-
@item.id.
|
704
|
+
it "has an id" do
|
705
|
+
expect(@item.id).to eq("1")
|
685
706
|
end
|
686
707
|
|
687
|
-
it "
|
688
|
-
@item.title.
|
708
|
+
it "has a title" do
|
709
|
+
expect(@item.title).to eq("Hello")
|
689
710
|
end
|
690
711
|
end
|
691
712
|
|
@@ -696,28 +717,31 @@ describe "SAXMachine" do
|
|
696
717
|
<author name="John Doe" role="writer" />
|
697
718
|
</item>
|
698
719
|
]
|
720
|
+
|
699
721
|
class AuthorElement
|
700
722
|
include SAXMachine
|
701
723
|
attribute :name
|
702
724
|
attribute :role
|
703
725
|
end
|
726
|
+
|
704
727
|
class ItemElement
|
705
728
|
include SAXMachine
|
706
|
-
element :author, :
|
729
|
+
element :author, class: AuthorElement
|
707
730
|
end
|
731
|
+
|
708
732
|
@item = ItemElement.parse(@xml)
|
709
733
|
end
|
710
734
|
|
711
|
-
it
|
712
|
-
@item.author.
|
735
|
+
it "has the child element" do
|
736
|
+
expect(@item.author).not_to be_nil
|
713
737
|
end
|
714
738
|
|
715
|
-
it
|
716
|
-
@item.author.name.
|
739
|
+
it "has the author name" do
|
740
|
+
expect(@item.author.name).to eq("John Doe")
|
717
741
|
end
|
718
742
|
|
719
|
-
it
|
720
|
-
@item.author.role.
|
743
|
+
it "has the author role" do
|
744
|
+
expect(@item.author.role).to eq("writer")
|
721
745
|
end
|
722
746
|
end
|
723
747
|
|
@@ -729,31 +753,34 @@ describe "SAXMachine" do
|
|
729
753
|
<author name="Jane Doe" role="artist" />
|
730
754
|
</item>
|
731
755
|
]
|
756
|
+
|
732
757
|
class AuthorElement2
|
733
758
|
include SAXMachine
|
734
759
|
attribute :name
|
735
760
|
attribute :role
|
736
761
|
end
|
762
|
+
|
737
763
|
class ItemElement2
|
738
764
|
include SAXMachine
|
739
|
-
elements :author, :
|
765
|
+
elements :author, as: :authors, class: AuthorElement2
|
740
766
|
end
|
767
|
+
|
741
768
|
@item = ItemElement2.parse(@xml)
|
742
769
|
end
|
743
770
|
|
744
|
-
it
|
745
|
-
@item.authors.
|
746
|
-
@item.authors.count.
|
771
|
+
it "has the child elements" do
|
772
|
+
expect(@item.authors).not_to be_nil
|
773
|
+
expect(@item.authors.count).to eq(2)
|
747
774
|
end
|
748
775
|
|
749
|
-
it
|
750
|
-
@item.authors.first.name.
|
751
|
-
@item.authors.last.name.
|
776
|
+
it "has the author names" do
|
777
|
+
expect(@item.authors.first.name).to eq("John Doe")
|
778
|
+
expect(@item.authors.last.name).to eq("Jane Doe")
|
752
779
|
end
|
753
780
|
|
754
|
-
it
|
755
|
-
@item.authors.first.role.
|
756
|
-
@item.authors.last.role.
|
781
|
+
it "has the author roles" do
|
782
|
+
expect(@item.authors.first.role).to eq("writer")
|
783
|
+
expect(@item.authors.last.role).to eq("artist")
|
757
784
|
end
|
758
785
|
end
|
759
786
|
|
@@ -764,28 +791,31 @@ describe "SAXMachine" do
|
|
764
791
|
<author role="writer">John Doe</author>
|
765
792
|
</item>
|
766
793
|
]
|
794
|
+
|
767
795
|
class AuthorElement3
|
768
796
|
include SAXMachine
|
769
797
|
value :name
|
770
798
|
attribute :role
|
771
799
|
end
|
800
|
+
|
772
801
|
class ItemElement3
|
773
802
|
include SAXMachine
|
774
|
-
element :author, :
|
803
|
+
element :author, class: AuthorElement3
|
775
804
|
end
|
805
|
+
|
776
806
|
@item = ItemElement3.parse(@xml)
|
777
807
|
end
|
778
808
|
|
779
|
-
it
|
780
|
-
@item.author.
|
809
|
+
it "has the child elements" do
|
810
|
+
expect(@item.author).not_to be_nil
|
781
811
|
end
|
782
812
|
|
783
|
-
it
|
784
|
-
@item.author.name.
|
813
|
+
it "has the author names" do
|
814
|
+
expect(@item.author.name).to eq("John Doe")
|
785
815
|
end
|
786
816
|
|
787
|
-
it
|
788
|
-
@item.author.role.
|
817
|
+
it "has the author roles" do
|
818
|
+
expect(@item.author.role).to eq("writer")
|
789
819
|
end
|
790
820
|
end
|
791
821
|
|
@@ -798,41 +828,64 @@ describe "SAXMachine" do
|
|
798
828
|
<author role="artist">Jane Doe</author>
|
799
829
|
</item>
|
800
830
|
]
|
831
|
+
|
801
832
|
class AuthorElement4
|
802
833
|
include SAXMachine
|
803
834
|
value :name
|
804
835
|
attribute :role
|
805
836
|
end
|
837
|
+
|
806
838
|
class ItemElement4
|
807
839
|
include SAXMachine
|
808
840
|
element :title
|
809
|
-
elements :author, :
|
841
|
+
elements :author, as: :authors, class: AuthorElement4
|
810
842
|
|
811
843
|
def title=(blah)
|
812
|
-
#raise 'woo'
|
813
844
|
@title = blah
|
814
845
|
end
|
815
846
|
end
|
847
|
+
|
816
848
|
@item = ItemElement4.parse(@xml)
|
817
849
|
end
|
818
850
|
|
819
|
-
it
|
820
|
-
@item.title.
|
851
|
+
it "has the title" do
|
852
|
+
expect(@item.title).to eq("sweet")
|
821
853
|
end
|
822
854
|
|
823
|
-
it
|
824
|
-
@item.authors.
|
825
|
-
@item.authors.count.
|
855
|
+
it "has the child elements" do
|
856
|
+
expect(@item.authors).not_to be_nil
|
857
|
+
expect(@item.authors.count).to eq(2)
|
826
858
|
end
|
827
859
|
|
828
|
-
it
|
829
|
-
@item.authors.first.name.
|
830
|
-
@item.authors.last.name.
|
860
|
+
it "has the author names" do
|
861
|
+
expect(@item.authors.first.name).to eq("John Doe")
|
862
|
+
expect(@item.authors.last.name).to eq("Jane Doe")
|
863
|
+
end
|
864
|
+
|
865
|
+
it "has the author roles" do
|
866
|
+
expect(@item.authors.first.role).to eq("writer")
|
867
|
+
expect(@item.authors.last.role).to eq("artist")
|
868
|
+
end
|
869
|
+
end
|
870
|
+
|
871
|
+
describe "with error handling" do
|
872
|
+
before do
|
873
|
+
@xml = %[
|
874
|
+
<item id="1">
|
875
|
+
<title>sweet</title>
|
876
|
+
]
|
877
|
+
|
878
|
+
class ItemElement5
|
879
|
+
include SAXMachine
|
880
|
+
element :title
|
881
|
+
end
|
882
|
+
|
883
|
+
@errors = []
|
884
|
+
@item = ItemElement5.parse(@xml, ->(x) { @errors << x })
|
831
885
|
end
|
832
886
|
|
833
|
-
it
|
834
|
-
@
|
835
|
-
@item.authors.last.role.should == 'artist'
|
887
|
+
it "has error" do
|
888
|
+
expect(@errors.uniq.size).to eq(1)
|
836
889
|
end
|
837
890
|
end
|
838
891
|
end
|