multi_xml 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of multi_xml might be problematic. Click here for more details.

@@ -6,28 +6,16 @@ module MultiXml
6
6
  extend self
7
7
  def parse_error; ::REXML::ParseException; end
8
8
 
9
- CONTENT_ROOT = '__content__'.freeze unless defined?(CONTENT_ROOT)
10
-
11
- # Parse an XML Document string or IO into a simple hash using REXML
9
+ # Parse an XML Document IO into a simple hash using REXML
12
10
  #
13
11
  # xml::
14
- # XML Document string or IO to parse
12
+ # XML Document IO to parse
15
13
  def parse(xml)
16
- if !xml.respond_to?(:read)
17
- xml = StringIO.new(xml || '')
18
- end
19
-
20
- char = xml.getc
21
- if char.nil?
22
- {}
14
+ doc = REXML::Document.new(xml)
15
+ if doc.root
16
+ merge_element!({}, doc.root)
23
17
  else
24
- xml.ungetc(char)
25
- doc = REXML::Document.new(xml)
26
- if doc.root
27
- merge_element!({}, doc.root)
28
- else
29
- raise REXML::ParseException, "The document #{doc.to_s.inspect} does not have a valid root"
30
- end
18
+ raise REXML::ParseException, "The document #{doc.to_s.inspect} does not have a valid root"
31
19
  end
32
20
  end
33
21
 
@@ -72,7 +60,7 @@ module MultiXml
72
60
  # must use value to prevent double-escaping
73
61
  texts = ''
74
62
  element.texts.each { |t| texts << t.value }
75
- merge!(hash, CONTENT_ROOT, texts)
63
+ merge!(hash, MultiXml::CONTENT_ROOT, texts)
76
64
  end
77
65
  end
78
66
 
@@ -118,7 +106,7 @@ module MultiXml
118
106
  # element::
119
107
  # XML element to be checked.
120
108
  def empty_content?(element)
121
- element.texts.join.blank?
109
+ element.texts.join.strip.empty?
122
110
  end
123
111
  end
124
112
  end
@@ -1,3 +1,3 @@
1
1
  module MultiXml
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -1,26 +1,24 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  require File.expand_path('../lib/multi_xml/version', __FILE__)
3
3
 
4
- Gem::Specification.new do |s|
5
- s.add_development_dependency('libxml-ruby', '~> 1.1')
6
- s.add_development_dependency('maruku', '~> 0.6')
7
- s.add_development_dependency('nokogiri', '~> 1.4')
8
- s.add_development_dependency('rake', '~> 0.8')
9
- s.add_development_dependency('rspec', '~> 2.5')
10
- s.add_development_dependency('simplecov', '~> 0.4')
11
- s.add_development_dependency('yard', '~> 0.6')
12
- s.add_development_dependency('ZenTest', '~> 4.5')
13
- s.name = 'multi_xml'
14
- s.version = MultiXml::VERSION
15
- s.platform = Gem::Platform::RUBY
16
- s.authors = ["Erik Michaels-Ober"]
17
- s.email = ['sferik@gmail.com']
18
- s.homepage = 'http://rubygems.org/gems/multi_xml'
19
- s.summary = %q{A generic swappable back-end for XML parsing}
20
- s.description = %q{A gem to provide swappable XML backends utilizing LibXML, Nokogiri, or REXML.}
21
- s.rubyforge_project = 'multi_xml'
22
- s.files = `git ls-files`.split("\n")
23
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
- s.require_paths = ['lib']
4
+ Gem::Specification.new do |gem|
5
+ gem.add_development_dependency 'ZenTest', '~> 4.5'
6
+ gem.add_development_dependency 'maruku', '~> 0.6'
7
+ gem.add_development_dependency 'nokogiri', '~> 1.4'
8
+ gem.add_development_dependency 'rake', '~> 0.9'
9
+ gem.add_development_dependency 'rspec', '~> 2.6'
10
+ gem.add_development_dependency 'simplecov', '~> 0.4'
11
+ gem.add_development_dependency 'yard', '~> 0.7'
12
+ gem.name = 'multi_xml'
13
+ gem.version = MultiXml::VERSION
14
+ gem.platform = Gem::Platform::RUBY
15
+ gem.author = "Erik Michaels-Ober"
16
+ gem.email = 'sferik@gmail.com'
17
+ gem.homepage = 'https://github.com/sferik/multi_xml'
18
+ gem.summary = %q{A generic swappable back-end for XML parsing}
19
+ gem.description = %q{A gem to provide swappable XML backends utilizing LibXML, Nokogiri, or REXML.}
20
+ gem.files = `git ls-files`.split("\n")
21
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ gem.require_paths = ['lib']
26
24
  end
@@ -1,4 +1,3 @@
1
1
  require 'simplecov'
2
2
  SimpleCov.start
3
3
  require 'multi_xml'
4
- require 'rspec'
@@ -1,4 +1,5 @@
1
1
  require 'helper'
2
+ require 'parser_shared_example'
2
3
 
3
4
  class MockDecoder; end
4
5
 
@@ -6,16 +7,16 @@ describe "MultiXml" do
6
7
  context "Parsers" do
7
8
  it "should default to the best available gem" do
8
9
  pending
9
- MultiXml.parser.name.should == 'MultiXml::Parsers::Rexml'
10
+ MultiXml.parser.name.should be == 'MultiXml::Parsers::Rexml'
10
11
  require 'nokogiri'
11
- MultiXml.parser.name.should == 'MultiXml::Parsers::Nokogiri'
12
+ MultiXml.parser.name.should be == 'MultiXml::Parsers::Nokogiri'
12
13
  require 'libxml'
13
14
  MultiXml.parser.name.should == 'MultiXml::Parsers::Libxml'
14
15
  end
15
16
 
16
17
  it "should be settable via a symbol" do
17
- MultiXml.parser = :libxml
18
- MultiXml.parser.name.should == 'MultiXml::Parsers::Libxml'
18
+ MultiXml.parser = :nokogiri
19
+ MultiXml.parser.name.should == 'MultiXml::Parsers::Nokogiri'
19
20
  end
20
21
 
21
22
  it "should be settable via a class" do
@@ -24,554 +25,16 @@ describe "MultiXml" do
24
25
  end
25
26
  end
26
27
 
27
- Dir.glob('lib/multi_xml/parsers/**/*.rb').map{|file| File.basename(file, ".rb").split('_').map{|s| s.capitalize}.join('')}.each do |parser|
28
- context "Parsers::#{parser}" do
29
- before do
30
- begin
31
- MultiXml.parser = parser
32
- rescue LoadError
33
- pending "Parser #{parser} couldn't be loaded"
34
- end
35
- end
36
-
37
- describe ".parse" do
38
- context "a blank string" do
39
- before do
40
- @xml = ''
41
- end
42
-
43
- it "should return an empty Hash" do
44
- MultiXml.parse(@xml).should == {}
45
- end
46
- end
47
-
48
- context "a whitespace string" do
49
- before do
50
- @xml = ' '
51
- end
52
-
53
- it "should return an empty Hash" do
54
- MultiXml.parse(@xml).should == {}
55
- end
56
- end
57
-
58
- context "an invalid XML document" do
59
- before do
60
- @xml = '<open></close>'
61
- end
62
-
63
- it "should raise MultiXml::ParseError" do
64
- lambda do
65
- MultiXml.parse(@xml)
66
- end.should raise_error(MultiXml::ParseError)
67
- end
68
- end
69
-
70
- context "a valid XML document" do
71
- before do
72
- @xml = '<user/>'
73
- end
74
-
75
- it "should parse correctly" do
76
- MultiXml.parse(@xml).should == {'user' => nil}
77
- end
78
-
79
- context "with CDATA" do
80
- before do
81
- @xml = '<user><![CDATA[Erik Michaels-Ober]]></user>'
82
- end
83
-
84
- it "should return the correct CDATA" do
85
- MultiXml.parse(@xml)['user'].should == "Erik Michaels-Ober"
86
- end
87
- end
88
-
89
- context "with content" do
90
- before do
91
- @xml = '<user>Erik Michaels-Ober</user>'
92
- end
93
-
94
- it "should return the correct content" do
95
- MultiXml.parse(@xml)['user'].should == "Erik Michaels-Ober"
96
- end
97
- end
98
-
99
- context "with an attribute" do
100
- before do
101
- @xml = '<user name="Erik Michaels-Ober"/>'
102
- end
103
-
104
- it "should return the correct attribute" do
105
- MultiXml.parse(@xml)['user']['name'].should == "Erik Michaels-Ober"
106
- end
107
- end
108
-
109
- context "with multiple attributes" do
110
- before do
111
- @xml = '<user name="Erik Michaels-Ober" screen_name="sferik"/>'
112
- end
113
-
114
- it "should return the correct attributes" do
115
- MultiXml.parse(@xml)['user']['name'].should == "Erik Michaels-Ober"
116
- MultiXml.parse(@xml)['user']['screen_name'].should == "sferik"
117
- end
118
- end
119
-
120
- context "with :symbolize_keys => true" do
121
- before do
122
- @xml = '<user><name>Erik Michaels-Ober</name></user>'
123
- end
124
-
125
- it "should symbolize keys" do
126
- MultiXml.parse(@xml, :symbolize_keys => true).should == {:user => {:name => "Erik Michaels-Ober"}}
127
- end
128
- end
129
-
130
- context "when value is true" do
131
- before do
132
- pending
133
- @xml = '<tag>true</tag>'
134
- end
135
-
136
- it "should return true" do
137
- MultiXml.parse(@xml)['tag'].should be_true
138
- end
139
- end
140
-
141
- context "when value is false" do
142
- before do
143
- pending
144
- @xml = '<tag>false</tag>'
145
- end
146
-
147
- it "should return false" do
148
- MultiXml.parse(@xml)['tag'].should be_false
149
- end
150
- end
151
-
152
- context "when key is id" do
153
- before do
154
- pending
155
- @xml = '<id>1</id>'
156
- end
157
-
158
- it "should return a Fixnum" do
159
- MultiXml.parse(@xml)['id'].should be_a(Fixnum)
160
- end
161
-
162
- it "should return the correct number" do
163
- MultiXml.parse(@xml)['id'].should == 1
164
- end
165
- end
166
-
167
- context "when key contains _id" do
168
- before do
169
- pending
170
- @xml = '<tag_id>1</tag_id>'
171
- end
172
-
173
- it "should return a Fixnum" do
174
- MultiXml.parse(@xml)['tag_id'].should be_a(Fixnum)
175
- end
176
-
177
- it "should return the correct number" do
178
- MultiXml.parse(@xml)['tag_id'].should == 1
179
- end
180
- end
181
-
182
- context "with an attribute type=\"boolean\"" do
183
- %w(true false).each do |boolean|
184
- context "when #{boolean}" do
185
- it "should return #{boolean}" do
186
- xml = "<tag type=\"boolean\">#{boolean}</tag>"
187
- MultiXml.parse(xml)['tag'].should instance_eval("be_#{boolean}")
188
- end
189
- end
190
- end
191
-
192
- context "when 1" do
193
- before do
194
- @xml = '<tag type="boolean">1</tag>'
195
- end
196
-
197
- it "should return true" do
198
- MultiXml.parse(@xml)['tag'].should be_true
199
- end
200
- end
201
-
202
- context "when 0" do
203
- before do
204
- @xml = '<tag type="boolean">0</tag>'
205
- end
206
-
207
- it "should return false" do
208
- MultiXml.parse(@xml)['tag'].should be_false
209
- end
210
- end
211
- end
212
-
213
- context "with an attribute type=\"integer\"" do
214
- context "with a positive integer" do
215
- before do
216
- @xml = '<tag type="integer">1</tag>'
217
- end
218
-
219
- it "should return a Fixnum" do
220
- MultiXml.parse(@xml)['tag'].should be_a(Fixnum)
221
- end
222
-
223
- it "should return a positive number" do
224
- MultiXml.parse(@xml)['tag'].should > 0
225
- end
226
-
227
- it "should return the correct number" do
228
- MultiXml.parse(@xml)['tag'].should == 1
229
- end
230
- end
231
-
232
- context "with a negative integer" do
233
- before do
234
- @xml = '<tag type="integer">-1</tag>'
235
- end
236
-
237
- it "should return a Fixnum" do
238
- MultiXml.parse(@xml)['tag'].should be_a(Fixnum)
239
- end
240
-
241
- it "should return a negative number" do
242
- MultiXml.parse(@xml)['tag'].should < 0
243
- end
244
-
245
- it "should return the correct number" do
246
- MultiXml.parse(@xml)['tag'].should == -1
247
- end
248
- end
249
- end
250
-
251
- context "with an attribute type=\"string\"" do
252
- before do
253
- @xml = '<tag type="string"></tag>'
254
- end
255
-
256
- it "should return a String" do
257
- MultiXml.parse(@xml)['tag'].should be_a(String)
258
- end
259
-
260
- it "should return the correct string" do
261
- MultiXml.parse(@xml)['tag'].should == ""
262
- end
263
- end
264
-
265
- context "with an attribute type=\"date\"" do
266
- before do
267
- @xml = '<tag type="date">1970-01-01</tag>'
268
- end
269
-
270
- it "should return a Date" do
271
- MultiXml.parse(@xml)['tag'].should be_a(Date)
272
- end
273
-
274
- it "should return the correct date" do
275
- MultiXml.parse(@xml)['tag'].should == Date.parse('1970-01-01')
276
- end
277
- end
278
-
279
- context "with an attribute type=\"datetime\"" do
280
- before do
281
- @xml = '<tag type="datetime">1970-01-01 00:00</tag>'
282
- end
283
-
284
- it "should return a Time" do
285
- MultiXml.parse(@xml)['tag'].should be_a(Time)
286
- end
287
-
288
- it "should return the correct time" do
289
- MultiXml.parse(@xml)['tag'].should == Time.parse('1970-01-01 00:00')
290
- end
291
- end
292
-
293
- context "with an attribute type=\"dateTime\"" do
294
- before do
295
- @xml = '<tag type="datetime">1970-01-01 00:00</tag>'
296
- end
297
-
298
- it "should return a Time" do
299
- MultiXml.parse(@xml)['tag'].should be_a(Time)
300
- end
301
-
302
- it "should return the correct time" do
303
- MultiXml.parse(@xml)['tag'].should == Time.parse('1970-01-01 00:00')
304
- end
305
- end
306
-
307
- context "with an attribute type=\"double\"" do
308
- before do
309
- @xml = '<tag type="double">3.14159265358979</tag>'
310
- end
311
-
312
- it "should return a Float" do
313
- MultiXml.parse(@xml)['tag'].should be_a(Float)
314
- end
315
-
316
- it "should return the correct number" do
317
- MultiXml.parse(@xml)['tag'].should == 3.14159265358979
318
- end
319
- end
320
-
321
- context "with an attribute type=\"decimal\"" do
322
- before do
323
- @xml = '<tag type="decimal">3.14159265358979323846264338327950288419716939937510</tag>'
324
- end
325
-
326
- it "should return a BigDecimal" do
327
- MultiXml.parse(@xml)['tag'].should be_a(BigDecimal)
328
- end
329
-
330
- it "should return the correct number" do
331
- MultiXml.parse(@xml)['tag'].should == 3.14159265358979323846264338327950288419716939937510
332
- end
333
- end
334
-
335
- context "with an attribute type=\"base64Binary\"" do
336
- before do
337
- @xml = '<tag type="base64Binary">aW1hZ2UucG5n</tag>'
338
- end
339
-
340
- it "should return a String" do
341
- MultiXml.parse(@xml)['tag'].should be_a(String)
342
- end
343
-
344
- it "should return the correct string" do
345
- MultiXml.parse(@xml)['tag'].should == "image.png"
346
- end
347
- end
348
-
349
- context "with an attribute type=\"yaml\"" do
350
- before do
351
- @xml = "<tag type=\"yaml\">--- \n1: should return an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n should_have_underscores: true\n</tag>"
352
- end
353
-
354
- it "should return a Hash" do
355
- MultiXml.parse(@xml)['tag'].should be_a(Hash)
356
- end
357
-
358
- it "should return the correctly parsed YAML" do
359
- MultiXml.parse(@xml)['tag'].should == {:message => "Have a nice day", 1 => "should return an integer", "array" => [{"should-have-dashes" => true, "should_have_underscores" => true}]}
360
- end
361
- end
362
-
363
- context "with an attribute type=\"file\"" do
364
- before do
365
- @xml = '<tag type="file" name="data.txt" content_type="text/plain">ZGF0YQ==</tag>'
366
- end
367
-
368
- it "should return a StringIO" do
369
- MultiXml.parse(@xml)['tag'].should be_a(StringIO)
370
- end
371
-
372
- it "should be decoded correctly" do
373
- MultiXml.parse(@xml)['tag'].string.should == 'data'
374
- end
375
-
376
- it "should have the correct file name" do
377
- MultiXml.parse(@xml)['tag'].original_filename.should == 'data.txt'
378
- end
379
-
380
- it "should have the correct content type" do
381
- MultiXml.parse(@xml)['tag'].content_type.should == 'text/plain'
382
- end
383
-
384
- context "with missing name and content type" do
385
- before do
386
- @xml = '<tag type="file">ZGF0YQ==</tag>'
387
- end
388
-
389
- it "should return a StringIO" do
390
- MultiXml.parse(@xml)['tag'].should be_a(StringIO)
391
- end
392
-
393
- it "should be decoded correctly" do
394
- MultiXml.parse(@xml)['tag'].string.should == 'data'
395
- end
396
-
397
- it "should have the default file name" do
398
- MultiXml.parse(@xml)['tag'].original_filename.should == 'untitled'
399
- end
400
-
401
- it "should have the default content type" do
402
- MultiXml.parse(@xml)['tag'].content_type.should == 'application/octet-stream'
403
- end
404
- end
405
- end
406
-
407
- context "with an attribute type=\"array\"" do
408
- before do
409
- @xml = '<users type="array"><user>Erik Michaels-Ober</user><user>Wynn Netherland</user></users>'
410
- end
411
-
412
- it "should return an Array" do
413
- MultiXml.parse(@xml)['users'].should be_a(Array)
414
- end
415
-
416
- it "should return the correct array" do
417
- MultiXml.parse(@xml)['users'].should == ["Erik Michaels-Ober", "Wynn Netherland"]
418
- end
419
- end
420
-
421
- %w(integer boolean date datetime yaml file).each do |type|
422
- context "with an empty attribute type=\"#{type}\"" do
423
- before do
424
- @xml = "<tag type=\"#{type}\"/>"
425
- end
426
-
427
- it "should return nil" do
428
- MultiXml.parse(@xml)['tag'].should be_nil
429
- end
430
- end
431
- end
432
-
433
- context "with an empty attribute type=\"array\"" do
434
- before do
435
- @xml = '<tag type="array"/>'
436
- end
437
-
438
- it "should return an empty Array" do
439
- MultiXml.parse(@xml)['tag'].should == []
440
- end
441
-
442
- context "with whitespace" do
443
- before do
444
- @xml = '<tag type="array"> </tag>'
445
- end
446
-
447
- it "should return an empty Array" do
448
- MultiXml.parse(@xml)['tag'].should == []
449
- end
450
- end
451
- end
452
-
453
- context "with XML entities" do
454
- before do
455
- @xml_entities = {
456
- "<" => "&lt;",
457
- ">" => "&gt;",
458
- '"' => "&quot;",
459
- "'" => "&apos;",
460
- "&" => "&amp;"
461
- }
462
- end
463
-
464
- context "in content" do
465
- it "should return unescaped XML entities" do
466
- @xml_entities.each do |key, value|
467
- xml = "<tag>#{value}</tag>"
468
- MultiXml.parse(xml)['tag'].should == key
469
- end
470
- end
471
- end
472
-
473
- context "in attribute" do
474
- it "should return unescaped XML entities" do
475
- @xml_entities.each do |key, value|
476
- xml = "<tag attribute=\"#{value}\"/>"
477
- MultiXml.parse(xml)['tag']['attribute'].should == key
478
- end
479
- end
480
- end
481
- end
482
-
483
- context "with dasherized tag" do
484
- before do
485
- @xml = '<tag-1/>'
486
- end
487
-
488
- it "should return undasherize tag" do
489
- MultiXml.parse(@xml).keys.should include('tag_1')
490
- end
491
- end
492
-
493
- context "with dasherized attribute" do
494
- before do
495
- @xml = '<tag attribute-1="1"></tag>'
496
- end
497
-
498
- it "should return undasherize attribute" do
499
- MultiXml.parse(@xml)['tag'].keys.should include('attribute_1')
500
- end
501
- end
502
-
503
- context "with children" do
504
- context "with attributes" do
505
- before do
506
- @xml = '<users><user name="Erik Michaels-Ober"/></users>'
507
- end
508
-
509
- it "should return the correct attributes" do
510
- MultiXml.parse(@xml)['users']['user']['name'].should == "Erik Michaels-Ober"
511
- end
512
- end
513
-
514
- context "with text" do
515
- before do
516
- @xml = '<user><name>Erik Michaels-Ober</name></user>'
517
- end
518
-
519
- it "should return the correct text" do
520
- MultiXml.parse(@xml)['user']['name'].should == "Erik Michaels-Ober"
521
- end
522
- end
523
-
524
- context "with an unrecognized attribute type" do
525
- before do
526
- @xml = '<user type="admin"><name>Erik Michaels-Ober</name></user>'
527
- end
528
-
529
- it "should pass through the type" do
530
- MultiXml.parse(@xml)['user']['type'].should == 'admin'
531
- end
532
- end
533
-
534
- context "with newlines and whitespace" do
535
- before do
536
- @xml = <<-XML
537
- <user>
538
- <name>Erik Michaels-Ober</name>
539
- </user>
540
- XML
541
- end
542
-
543
- it "should parse correctly" do
544
- MultiXml.parse(@xml).should == {"user" => {"name" => "Erik Michaels-Ober"}}
545
- end
546
- end
547
-
548
- # Babies having babies
549
- context "with children" do
550
- before do
551
- @xml = '<users><user name="Erik Michaels-Ober"><status text="Hello"/></user></users>'
552
- end
553
-
554
- it "should parse correctly" do
555
- MultiXml.parse(@xml).should == {"users" => {"user" => {"name" => "Erik Michaels-Ober", "status" => {"text" => "Hello"}}}}
556
- end
557
- end
558
- end
559
-
560
- context "with sibling children" do
561
- before do
562
- @xml = '<users><user>Erik Michaels-Ober</user><user>Wynn Netherland</user></users>'
563
- end
564
-
565
- it "should return an Array" do
566
- MultiXml.parse(@xml)['users']['user'].should be_a(Array)
567
- end
568
-
569
- it "should parse correctly" do
570
- MultiXml.parse(@xml).should == {"users" => {"user" => ["Erik Michaels-Ober", "Wynn Netherland"]}}
571
- end
572
- end
573
- end
28
+ [['LibXML', 'libxml'],
29
+ ['REXML', 'rexml/document'],
30
+ ['Nokogiri', 'nokogiri']].each do |parser|
31
+ begin
32
+ require parser.last
33
+ context "#{parser.first} parser" do
34
+ it_should_behave_like "a parser", parser.first
574
35
  end
36
+ rescue LoadError => e
37
+ puts "Tests not run for #{parser.first} due to a LoadError"
575
38
  end
576
39
  end
577
40
  end