sax-machine 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.travis.yml +14 -4
  4. data/Gemfile +5 -1
  5. data/Guardfile +2 -2
  6. data/HISTORY.md +23 -6
  7. data/README.md +111 -40
  8. data/Rakefile +4 -3
  9. data/lib/sax-machine.rb +11 -2
  10. data/lib/sax-machine/{sax_ancestor_config.rb → config/sax_ancestor.rb} +3 -7
  11. data/lib/sax-machine/{sax_attribute_config.rb → config/sax_attribute.rb} +4 -6
  12. data/lib/sax-machine/{sax_collection_config.rb → config/sax_collection.rb} +6 -10
  13. data/lib/sax-machine/{sax_element_config.rb → config/sax_element.rb} +16 -17
  14. data/lib/sax-machine/{sax_element_value_config.rb → config/sax_element_value.rb} +5 -7
  15. data/lib/sax-machine/{sax_handler.rb → handlers/sax_abstract_handler.rb} +28 -32
  16. data/lib/sax-machine/handlers/sax_nokogiri_handler.rb +16 -0
  17. data/lib/sax-machine/handlers/sax_ox_handler.rb +41 -0
  18. data/lib/sax-machine/sax_config.rb +9 -9
  19. data/lib/sax-machine/sax_configure.rb +1 -6
  20. data/lib/sax-machine/sax_document.rb +28 -17
  21. data/lib/sax-machine/version.rb +2 -2
  22. data/sax-machine.gemspec +8 -11
  23. data/spec/fixtures/atom-content.html +15 -0
  24. data/spec/{sax-machine → fixtures}/atom.xml +0 -0
  25. data/spec/sax-machine/sax_activerecord_spec.rb +23 -0
  26. data/spec/sax-machine/sax_configure_spec.rb +48 -0
  27. data/spec/sax-machine/sax_document_spec.rb +333 -280
  28. data/spec/sax-machine/sax_include_spec.rb +43 -0
  29. data/spec/spec_helper.rb +11 -2
  30. metadata +36 -41
  31. data/spec/benchmarks/amazon.xml +0 -40
  32. data/spec/benchmarks/benchmark.rb +0 -158
  33. data/spec/benchmarks/public_timeline.xml +0 -411
  34. data/spec/sax-machine/configure_sax_machine_spec.rb +0 -53
  35. 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 "should provide mass assignment through initialize method" do
14
- document = @klass.new(title: 'Title')
15
- document.title.should == '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 "should provide an accessor" do
18
+ it "provides an accessor" do
19
19
  document = @klass.new
20
20
  document.title = "Title"
21
- document.title.should == "Title"
21
+ expect(document.title).to eq("Title")
22
22
  end
23
23
 
24
- it "should allow introspection of the elements" do
25
- @klass.column_names.should =~ [:title]
24
+ it "allows introspection of the elements" do
25
+ expect(@klass.column_names).to match_array([:title])
26
26
  end
27
27
 
28
- it "should not overwrite the getter is there is already one present" do
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.should == "Title ***"
40
+ expect(document.title).to eq("Title ***")
40
41
  end
41
42
 
42
- it "should not overwrite the setter if there is already one present" do
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.title.should == "Title **"
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, :class => DateTime
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
- it "should be available" do
65
- @klass.data_class(:date).should == DateTime
110
+
111
+ it "is available" do
112
+ expect(@klass.data_class(:date)).to eq(DateTime)
66
113
  end
67
-
68
- it "should handle an integer class" do
114
+
115
+ it "handles an integer class" do
69
116
  @klass = Class.new do
70
117
  include SAXMachine
71
- element :number, :class => Integer
118
+ element :number, class: Integer
72
119
  end
120
+
73
121
  document = @klass.parse("<number>5</number>")
74
- document.number.should == 5
122
+ expect(document.number).to eq(5)
75
123
  end
76
-
77
- it "should handle an float class" do
124
+
125
+ it "handles an float class" do
78
126
  @klass = Class.new do
79
127
  include SAXMachine
80
- element :number, :class => Float
128
+ element :number, class: Float
81
129
  end
130
+
82
131
  document = @klass.parse("<number>5.5</number>")
83
- document.number.should == 5.5
84
- end
132
+ expect(document.number).to eq(5.5)
133
+ end
85
134
 
86
- it "should handle an string class" do
135
+ it "handles an string class" do
87
136
  @klass = Class.new do
88
137
  include SAXMachine
89
- element :number, :class => String
138
+ element :number, class: String
90
139
  end
140
+
91
141
  document = @klass.parse("<number>5.5</number>")
92
- document.number.should == "5.5"
142
+ expect(document.number).to eq("5.5")
93
143
  end
94
-
95
- it "should handle a time class" do
144
+
145
+ it "handles a time class" do
96
146
  @klass = Class.new do
97
147
  include SAXMachine
98
- element :time, :class => 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.should == Time.utc(1994, 2, 4, 6, 20, 0, 0)
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 "should be available" do
157
+ it "is available" do
107
158
  @klass = Class.new do
108
159
  include SAXMachine
109
- element :date, :required => true
160
+ element :date, required: true
110
161
  end
111
- @klass.required?(:date).should be_true
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 "should save the element text for a second tag" do
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.should == "Paul"
173
- document.title.should == "My 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.should == []
194
+ expect(document.items).to eq([])
189
195
  end
190
196
 
191
- it "should not overwrite the setter if there is already one present" do
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.should == [1, 2, 3]
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, :as => :summary
218
+ element :description, as: :summary
213
219
  end
214
220
  end
215
221
 
216
- it "should provide an accessor using the 'as' name" do
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.should == "a small summary"
225
+ expect(document.summary).to eq("a small summary")
220
226
  end
221
227
 
222
- it "should save the element text into the 'as' accessor" do
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.should == "here is a description"
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, :value => :href, :with => {:foo => "bar"}
239
+ element :link, value: :href, with: { foo: "bar" }
234
240
  end
235
241
  end
236
242
 
237
- it "should save the value of a matching element" do
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.should == "test"
245
+ expect(document.link).to eq("test")
240
246
  end
241
247
 
242
- it "should save the value of the first matching element" do
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.should == "first"
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, :value => :href, :as => :url, :with => {:foo => "bar"}
252
- element :link, :value => :href, :as => :second_url, :with => {:asdf => "jkl"}
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 "should save the value of the first matching element" do
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.should == "first"
259
- document.second_url.should == "second"
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, :with => {:foo => "bar"}
274
+ element :link, with: { foo: "bar" }
270
275
  end
271
276
  end
272
277
 
273
- it "should save the text of an element that has matching attributes" do
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.should == "match"
280
+ expect(document.link).to eq("match")
276
281
  end
277
282
 
278
- it "should not save the text of an element that doesn't have matching attributes" do
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.should be_nil
285
+ expect(document.link).to be_nil
281
286
  end
282
287
 
283
- it "should save the text of an element that has matching attributes when it is the second of that type" do
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.should == "match"
286
-
290
+ expect(document.link).to eq("match")
287
291
  end
288
292
 
289
- it "should save the text of an element that has matching attributes plus a few more" do
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.should == "match"
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, :as => :first, :with => {:foo => "bar"}
300
- element :link, :as => :second, :with => {:asdf => "jkl"}
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 "should match the first element" do
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.should == "first match"
310
+ expect(document.first).to eq("first match")
307
311
  end
308
312
 
309
- it "should match the second element" do
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.should == "second match"
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, :with => {:foo => /ar$/}
323
+ element :link, with: { foo: /ar$/ }
320
324
  end
321
325
  end
322
326
 
323
- it "should save the text of an element that has matching attributes" do
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.should == "match"
329
+ expect(document.link).to eq("match")
326
330
  end
327
331
 
328
- it "should not save the text of an element that doesn't have matching attributes" do
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.should be_nil
334
+ expect(document.link).to be_nil
331
335
  end
332
336
 
333
- it "should save the text of an element that has matching attributes when it is the second of that type" do
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.should == "match"
339
+ expect(document.link).to eq("match")
336
340
  end
337
341
 
338
- it "should save the text of an element that has matching attributes plus a few more" do
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.should == "match"
344
+ expect(document.link).to eq("match")
341
345
  end
342
346
  end
343
- end # using the 'with' option
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, :value => :foo
353
+ element :link, value: :foo
350
354
  end
351
355
  end
352
356
 
353
- it "should save the attribute value" do
357
+ it "saves the attribute value" do
354
358
  document = @klass.parse("<link foo='test'>hello</link>")
355
- document.link.should == 'test'
359
+ expect(document.link).to eq("test")
356
360
  end
357
361
 
358
- it "should save the attribute value when there is no text enclosed by the tag" do
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.should == 'test'
364
+ expect(document.link).to eq("test")
361
365
  end
362
366
 
363
- it "should save the attribute value when the tag close is in the open" do
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.should == 'test'
369
+ expect(document.link).to eq("test")
366
370
  end
367
371
 
368
- it "should save two different attribute values on a single tag" do
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, :value => :foo, :as => :first
372
- element :link, :value => :bar, :as => :second
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.should == "foo value"
376
- document.second.should == "bar value"
380
+ expect(document.first).to eq("foo value")
381
+ expect(document.second).to eq("bar value")
377
382
  end
378
383
 
379
- it "should not fail if one of the attribute hasn't been defined" do
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, :value => :foo, :as => :first
383
- element :link, :value => :bar, :as => :second
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.should == "foo value"
387
- document.second.should be_nil
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, :value => :foo, :as => :link_foo
397
- element :link, :value => :bar, :as => :link_bar
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 "should parse the element and attribute values" do
407
+ it "parses the element and attribute values" do
402
408
  document = @klass.parse("<link foo='test1' bar='test2'>hello</link>")
403
- document.link.should == 'hello'
404
- document.link_foo.should == 'test1'
405
- document.link_bar.should == 'test2'
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, :as => :entries
422
+ elements :entry, as: :entries
418
423
  end
419
424
  end
420
425
 
421
- it "should provide a collection accessor" do
426
+ it "provides a collection accessor" do
422
427
  document = @klass.new
423
428
  document.entries << :foo
424
- document.entries.should == [:foo]
429
+ expect(document.entries).to eq([:foo])
425
430
  end
426
431
 
427
- it "should parse a single element" do
432
+ it "parses a single element" do
428
433
  document = @klass.parse("<entry>hello</entry>")
429
- document.entries.should == ["hello"]
434
+ expect(document.entries).to eq(["hello"])
430
435
  end
431
436
 
432
- it "should parse multiple elements" do
437
+ it "parses multiple elements" do
433
438
  document = @klass.parse("<xml><entry>hello</entry><entry>world</entry></xml>")
434
- document.entries.should == ["hello", "world"]
439
+ expect(document.entries).to eq(["hello", "world"])
435
440
  end
436
441
 
437
- it "should parse multiple elements when taking an attribute value" do
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, :as => :entries, :value => :foo
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.should == ["asdf", "jkl"]
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, :as => :items, :with => {:type => 'Bar'}, :class => Bar
466
- elements :item, :as => :items, :with => {:type => /Foo/}, :class => Foo
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 "should cast into the correct class" do
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.should == 2
473
- document.items.first.should be_a(Bar)
474
- document.items.first.title.should == "Bar title"
475
- document.items.last.should be_a(Foo)
476
- document.items.last.title.should == "Foo 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, :as => :entries, :class => Foo
495
+ elements :entry, as: :entries, class: Foo
489
496
  end
490
497
  end
491
498
 
492
- it "should parse a single element with children" do
499
+ it "parses a single element with children" do
493
500
  document = @klass.parse("<entry><title>a title</title></entry>")
494
- document.entries.size.should == 1
495
- document.entries.first.title.should == "a 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 "should parse multiple elements with children" do
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.should == 2
501
- document.entries.first.title.should == "title 1"
502
- document.entries.last.title.should == "title 2"
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 "should not parse a top level element that is specified only in a child" do
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.should == 1
508
- document.entries.first.title.should == "correct 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 "should parse elements, and make attributes and inner text available" do
518
+ it "parses elements, and make attributes and inner text available" do
512
519
  class Related
513
520
  include SAXMachine
514
- element 'related', :as=>:item
515
- element 'related', :as=>:attr, :value=>'attr'
521
+ element "related", as: :item
522
+ element "related", as: :attr, value: "attr"
516
523
  end
524
+
517
525
  class Foo
518
- elements 'related', :as=>'items', :class=>Related
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.should_not be_nil
523
- doc.items.size.should == 2
524
- doc.items.first.item.should == 'something'
525
- doc.items.last.item.should == 'somethingelse'
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 "should parse out an attribute value from the tag that starts the collection" do
536
+ it "parses out an attribute value from the tag that starts the collection" do
529
537
  class Foo
530
- element :entry, :value => :href, :as => :url
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.should == 1
534
- document.entries.first.title.should == "paul"
535
- document.entries.first.url.should == "http://pauldix.net"
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 'should automatically convert dashes to underscores' do
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('<dashed-element>Text</dashed-element>')
548
- parsed.dashed_element.should eq "Text"
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('spec/sax-machine/atom.xml')
563
+ @xml = File.read("spec/fixtures/atom.xml")
564
+
555
565
  class AtomEntry
556
566
  include SAXMachine
557
567
  element :title
558
- element :name, :as => :author
559
- element "feedburner:origLink", :as => :url
560
- element :link, :as => :alternate, :value => :href, :with => {:type => "text/html", :rel => "alternate"}
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, :value => :href, :as => :url, :with => {:type => "text/html"}
570
- element :link, :value => :href, :as => :feed_url, :with => {:type => "application/atom+xml"}
571
- elements :entry, :as => :entries, :class => AtomEntry
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
- it "should parse the url" do
576
- f = Atom.parse(@xml)
577
- f.url.should == "http://www.pauldix.net/"
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&param2=2")
593
+ expect(@feed.entries.first.alternate).to eq("http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~3/383536354/marshal-data-to.html?param1=1&param2=2")
578
594
  end
579
595
 
580
- it "should parse entry url" do
581
- f = Atom.parse(@xml)
582
- f.entries.first.url.should == "http://www.pauldix.net/2008/09/marshal-data-to.html?param1=1&param2=2"
583
- f.entries.first.alternate.should == "http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~3/383536354/marshal-data-to.html?param1=1&param2=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
- class CategoryCollection;
602
- end
615
+
616
+ class CategoryCollection; end
617
+
603
618
  class Category
604
619
  include SAXMachine
605
620
  attr_accessor :id
606
- element :category, :value => :id, :as => :id
621
+ element :category, value: :id, as: :id
607
622
  element :title
608
- element :categories, :as => :collection, :class => CategoryCollection
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, :as => :categories, :class => 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 "should parse the first category" do
619
- @collection.categories.first.id.should == "1"
620
- @collection.categories.first.title.should == "First"
621
- @collection.categories.first.ancestor.should == @collection
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 "should parse the nested category" do
625
- @collection.categories.first.collection.categories.first.id.should == "2"
626
- @collection.categories.first.collection.categories.first.title.should == "Second"
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, :value => :id, :as => :id
665
+ element :category, value: :id, as: :id
648
666
  element :title
649
- elements :category, :as => :categories, :class => CategoryTree
667
+ elements :category, as: :categories, class: CategoryTree
650
668
  end
669
+
651
670
  @collection = CategoryTree.parse(@xml)
652
671
  end
653
672
 
654
- it "should parse the first category" do
655
- @collection.categories.first.id.should == "1"
656
- @collection.categories.first.title.should == "First"
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 "should parse the nested category" do
660
- @collection.categories.first.categories.first.id.should == "2"
661
- @collection.categories.first.categories.first.title.should == "Second"
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, :value => "id", :as => :id
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 "should have an id" do
684
- @item.id.should == "1"
704
+ it "has an id" do
705
+ expect(@item.id).to eq("1")
685
706
  end
686
707
 
687
- it "should have a title" do
688
- @item.title.should == "Hello"
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, :class => AuthorElement
729
+ element :author, class: AuthorElement
707
730
  end
731
+
708
732
  @item = ItemElement.parse(@xml)
709
733
  end
710
734
 
711
- it 'should have the child element' do
712
- @item.author.should_not be_nil
735
+ it "has the child element" do
736
+ expect(@item.author).not_to be_nil
713
737
  end
714
738
 
715
- it 'should have the author name' do
716
- @item.author.name.should == 'John Doe'
739
+ it "has the author name" do
740
+ expect(@item.author.name).to eq("John Doe")
717
741
  end
718
742
 
719
- it 'should have the author role' do
720
- @item.author.role.should == 'writer'
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, :as => :authors, :class => AuthorElement2
765
+ elements :author, as: :authors, class: AuthorElement2
740
766
  end
767
+
741
768
  @item = ItemElement2.parse(@xml)
742
769
  end
743
770
 
744
- it 'should have the child elements' do
745
- @item.authors.should_not be_nil
746
- @item.authors.count.should == 2
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 'should have the author names' do
750
- @item.authors.first.name.should == 'John Doe'
751
- @item.authors.last.name.should == 'Jane Doe'
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 'should have the author roles' do
755
- @item.authors.first.role.should == 'writer'
756
- @item.authors.last.role.should == 'artist'
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, :class => AuthorElement3
803
+ element :author, class: AuthorElement3
775
804
  end
805
+
776
806
  @item = ItemElement3.parse(@xml)
777
807
  end
778
808
 
779
- it 'should have the child elements' do
780
- @item.author.should_not be_nil
809
+ it "has the child elements" do
810
+ expect(@item.author).not_to be_nil
781
811
  end
782
812
 
783
- it 'should have the author names' do
784
- @item.author.name.should == 'John Doe'
813
+ it "has the author names" do
814
+ expect(@item.author.name).to eq("John Doe")
785
815
  end
786
816
 
787
- it 'should have the author roles' do
788
- @item.author.role.should == 'writer'
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, :as => :authors, :class => AuthorElement4
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 'should have the title' do
820
- @item.title.should == 'sweet'
851
+ it "has the title" do
852
+ expect(@item.title).to eq("sweet")
821
853
  end
822
854
 
823
- it 'should have the child elements' do
824
- @item.authors.should_not be_nil
825
- @item.authors.count.should == 2
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 'should have the author names' do
829
- @item.authors.first.name.should == 'John Doe'
830
- @item.authors.last.name.should == 'Jane Doe'
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 'should have the author roles' do
834
- @item.authors.first.role.should == 'writer'
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