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.
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