multi_xml 0.1.0 → 0.1.1
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.
Potentially problematic release.
This version of multi_xml might be problematic. Click here for more details.
- data/.rspec +1 -0
- data/Gemfile.lock +1 -1
- data/README.rdoc +1 -0
- data/lib/multi_xml.rb +11 -7
- data/lib/multi_xml/core_extensions.rb +59 -0
- data/lib/multi_xml/parsers/libxml.rb +8 -8
- data/lib/multi_xml/parsers/nokogiri.rb +8 -8
- data/lib/multi_xml/parsers/rexml.rb +9 -11
- data/lib/multi_xml/version.rb +1 -1
- data/multi_xml.gemspec +2 -2
- data/spec/multi_xml_spec.rb +112 -99
- metadata +7 -6
data/.rspec
CHANGED
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
= MultiXML
|
2
|
+
==== A generic swappable back-end for XML parsing
|
2
3
|
|
3
4
|
Lots of Ruby libraries utilize XML parsing in some form, and everyone has their favorite XML library. In order to best support multiple XML parsers and libraries, <tt>multi_xml</tt> is a general-purpose swappable XML backend library. You use it like so:
|
4
5
|
|
data/lib/multi_xml.rb
CHANGED
@@ -20,8 +20,8 @@ module MultiXml
|
|
20
20
|
unless defined?(PARSING)
|
21
21
|
PARSING = {
|
22
22
|
'symbol' => Proc.new{|symbol| symbol.to_sym},
|
23
|
-
'date' => Proc.new{|date|
|
24
|
-
'datetime' => Proc.new{|time|
|
23
|
+
'date' => Proc.new{|date| Date.parse(date)},
|
24
|
+
'datetime' => Proc.new{|time| Time.parse(time).utc rescue DateTime.parse(time).utc},
|
25
25
|
'integer' => Proc.new{|integer| integer.to_i},
|
26
26
|
'float' => Proc.new{|float| float.to_f},
|
27
27
|
'decimal' => Proc.new{|number| BigDecimal(number)},
|
@@ -89,9 +89,8 @@ module MultiXml
|
|
89
89
|
# <tt>:symbolize_keys</tt> :: If true, will use symbols instead of strings for the keys.
|
90
90
|
def parse(xml, options={})
|
91
91
|
xml.strip!
|
92
|
-
hash = typecast_xml_value(undasherize_keys(parser.parse(xml)))
|
92
|
+
hash = typecast_xml_value(undasherize_keys(parser.parse(xml))) || {}
|
93
93
|
hash = symbolize_keys(hash) if options[:symbolize_keys]
|
94
|
-
hash = {} if hash.nil?
|
95
94
|
hash
|
96
95
|
end
|
97
96
|
|
@@ -177,7 +176,7 @@ module MultiXml
|
|
177
176
|
when Hash
|
178
177
|
if value['type'] == 'array'
|
179
178
|
_, entries = wrap(value.detect{|key, value| key != 'type'})
|
180
|
-
if entries.
|
179
|
+
if entries.blank? || (c = value[CONTENT_ROOT] && c.blank?)
|
181
180
|
[]
|
182
181
|
else
|
183
182
|
case entries
|
@@ -199,12 +198,12 @@ module MultiXml
|
|
199
198
|
elsif value['type'] == 'string' && value['nil'] != 'true'
|
200
199
|
''
|
201
200
|
# blank or nil parsed values are represented by nil
|
202
|
-
elsif value.
|
201
|
+
elsif value.blank? || value['nil'] == 'true'
|
203
202
|
nil
|
204
203
|
# If the type is the only element which makes it then
|
205
204
|
# this still makes the value nil, except if type is
|
206
205
|
# a XML node(where type['value'] is a Hash)
|
207
|
-
elsif value['type'] && value.size == 1 && !value['type'].is_a?(
|
206
|
+
elsif value['type'] && value.size == 1 && !value['type'].is_a?(Hash)
|
208
207
|
nil
|
209
208
|
else
|
210
209
|
xml_value = value.inject({}) do |hash, (key, value)|
|
@@ -227,3 +226,8 @@ module MultiXml
|
|
227
226
|
end
|
228
227
|
end
|
229
228
|
end
|
229
|
+
|
230
|
+
library_files = Dir[File.join(File.dirname(__FILE__), "/multi_xml/**/*.rb")].sort
|
231
|
+
library_files.each do |file|
|
232
|
+
require file
|
233
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class Object #:nodoc:
|
2
|
+
# @return <TrueClass, FalseClass>
|
3
|
+
#
|
4
|
+
# @example [].blank? #=> true
|
5
|
+
# @example [1].blank? #=> false
|
6
|
+
# @example [nil].blank? #=> false
|
7
|
+
#
|
8
|
+
# Returns true if the object is nil or empty (if applicable)
|
9
|
+
def blank?
|
10
|
+
nil? || (respond_to?(:empty?) && empty?)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Numeric #:nodoc:
|
15
|
+
# @return <TrueClass, FalseClass>
|
16
|
+
#
|
17
|
+
# Numerics can't be blank
|
18
|
+
def blank?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class NilClass #:nodoc:
|
24
|
+
# @return <TrueClass, FalseClass>
|
25
|
+
#
|
26
|
+
# Nils are always blank
|
27
|
+
def blank?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class TrueClass #:nodoc:
|
33
|
+
# @return <TrueClass, FalseClass>
|
34
|
+
#
|
35
|
+
# True is not blank.
|
36
|
+
def blank?
|
37
|
+
false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class FalseClass #:nodoc:
|
42
|
+
# False is always blank.
|
43
|
+
def blank?
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class String #:nodoc:
|
49
|
+
# @example "".blank? #=> true
|
50
|
+
# @example " ".blank? #=> true
|
51
|
+
# @example " hey ho ".blank? #=> false
|
52
|
+
#
|
53
|
+
# @return <TrueClass, FalseClass>
|
54
|
+
#
|
55
|
+
# Strips out whitespace then tests if the string is empty.
|
56
|
+
def blank?
|
57
|
+
strip.empty?
|
58
|
+
end
|
59
|
+
end
|
@@ -7,19 +7,19 @@ module MultiXml
|
|
7
7
|
extend self
|
8
8
|
|
9
9
|
# Parse an XML Document string or IO into a simple hash using libxml.
|
10
|
-
#
|
10
|
+
# xml::
|
11
11
|
# XML Document string or IO to parse
|
12
|
-
def parse(
|
13
|
-
if !
|
14
|
-
|
12
|
+
def parse(xml)
|
13
|
+
if !xml.respond_to?(:read)
|
14
|
+
xml = StringIO.new(xml || '')
|
15
15
|
end
|
16
16
|
|
17
|
-
char =
|
17
|
+
char = xml.getc
|
18
18
|
if char.nil?
|
19
19
|
{}
|
20
20
|
else
|
21
|
-
|
22
|
-
LibXML::XML::Parser.io(
|
21
|
+
xml.ungetc(char)
|
22
|
+
LibXML::XML::Parser.io(xml).parse.to_hash
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -62,7 +62,7 @@ module LibXML #:nodoc:
|
|
62
62
|
end
|
63
63
|
|
64
64
|
# Remove content node if it is blank
|
65
|
-
if node_hash.length > 1 &&
|
65
|
+
if node_hash.length > 1 && node_hash[CONTENT_ROOT].blank?
|
66
66
|
node_hash.delete(CONTENT_ROOT)
|
67
67
|
end
|
68
68
|
|
@@ -7,19 +7,19 @@ module MultiXml
|
|
7
7
|
extend self
|
8
8
|
|
9
9
|
# Parse an XML Document string or IO into a simple hash using libxml / nokogiri.
|
10
|
-
#
|
10
|
+
# xml::
|
11
11
|
# XML Document string or IO to parse
|
12
|
-
def parse(
|
13
|
-
if !
|
14
|
-
|
12
|
+
def parse(xml)
|
13
|
+
if !xml.respond_to?(:read)
|
14
|
+
xml = StringIO.new(xml || '')
|
15
15
|
end
|
16
16
|
|
17
|
-
char =
|
17
|
+
char = xml.getc
|
18
18
|
if char.nil?
|
19
19
|
{}
|
20
20
|
else
|
21
|
-
|
22
|
-
doc = ::Nokogiri::XML(
|
21
|
+
xml.ungetc(char)
|
22
|
+
doc = ::Nokogiri::XML(xml)
|
23
23
|
raise doc.errors.first if doc.errors.length > 0
|
24
24
|
doc.to_hash
|
25
25
|
end
|
@@ -60,7 +60,7 @@ module MultiXml
|
|
60
60
|
end
|
61
61
|
|
62
62
|
# Remove content node if it is blank and there are child tags
|
63
|
-
if node_hash.length > 1 &&
|
63
|
+
if node_hash.length > 1 && node_hash[CONTENT_ROOT].blank?
|
64
64
|
node_hash.delete(CONTENT_ROOT)
|
65
65
|
end
|
66
66
|
|
@@ -10,25 +10,23 @@ module MultiXml
|
|
10
10
|
|
11
11
|
# Parse an XML Document string or IO into a simple hash
|
12
12
|
#
|
13
|
-
#
|
13
|
+
# xml::
|
14
14
|
# XML Document string or IO to parse
|
15
|
-
def parse(
|
16
|
-
if !
|
17
|
-
|
15
|
+
def parse(xml)
|
16
|
+
if !xml.respond_to?(:read)
|
17
|
+
xml = StringIO.new(xml || '')
|
18
18
|
end
|
19
19
|
|
20
|
-
char =
|
20
|
+
char = xml.getc
|
21
21
|
if char.nil?
|
22
22
|
{}
|
23
23
|
else
|
24
|
-
|
25
|
-
doc = REXML::Document.new(
|
26
|
-
|
24
|
+
xml.ungetc(char)
|
25
|
+
doc = REXML::Document.new(xml)
|
27
26
|
if doc.root
|
28
27
|
merge_element!({}, doc.root)
|
29
28
|
else
|
30
|
-
raise REXML::ParseException,
|
31
|
-
"The document #{doc.to_s.inspect} does not have a valid root"
|
29
|
+
raise REXML::ParseException, "The document #{doc.to_s.inspect} does not have a valid root"
|
32
30
|
end
|
33
31
|
end
|
34
32
|
end
|
@@ -120,7 +118,7 @@ module MultiXml
|
|
120
118
|
# element::
|
121
119
|
# XML element to be checked.
|
122
120
|
def empty_content?(element)
|
123
|
-
element.texts.join.
|
121
|
+
element.texts.join.blank?
|
124
122
|
end
|
125
123
|
end
|
126
124
|
end
|
data/lib/multi_xml/version.rb
CHANGED
data/multi_xml.gemspec
CHANGED
@@ -14,8 +14,8 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.authors = ["Erik Michaels-Ober"]
|
15
15
|
s.email = ["sferik@gmail.com"]
|
16
16
|
s.homepage = "http://rubygems.org/gems/multi_xml"
|
17
|
-
s.summary = %q{A
|
18
|
-
s.description =
|
17
|
+
s.summary = %q{A generic swappable back-end for XML parsing}
|
18
|
+
s.description = %q{A gem to provide swappable XML backends utilizing LibXML, Nokogiri, or REXML.}
|
19
19
|
s.rubyforge_project = "multi_xml"
|
20
20
|
s.files = `git ls-files`.split("\n")
|
21
21
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/spec/multi_xml_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
class MockDecoder
|
4
|
-
def self.parse(
|
4
|
+
def self.parse(xml)
|
5
5
|
'<tag>This is the contents</tag>'
|
6
6
|
end
|
7
7
|
end
|
@@ -37,81 +37,81 @@ describe "MultiXml" do
|
|
37
37
|
describe ".parse" do
|
38
38
|
context "a blank string" do
|
39
39
|
before do
|
40
|
-
@
|
40
|
+
@xml = ''
|
41
41
|
end
|
42
42
|
|
43
43
|
it "should return an empty Hash" do
|
44
|
-
MultiXml.parse(@
|
44
|
+
MultiXml.parse(@xml).should == {}
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
context "a whitespace string" do
|
49
49
|
before do
|
50
|
-
@
|
50
|
+
@xml = ' '
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should return an empty Hash" do
|
54
|
-
MultiXml.parse(@
|
54
|
+
MultiXml.parse(@xml).should == {}
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
context "a single-node document" do
|
59
59
|
|
60
60
|
before do
|
61
|
-
@
|
61
|
+
@xml = '<user/>'
|
62
62
|
end
|
63
63
|
|
64
64
|
it "should parse correctly" do
|
65
|
-
MultiXml.parse(@
|
65
|
+
MultiXml.parse(@xml).should == {'user' => nil}
|
66
66
|
end
|
67
67
|
|
68
68
|
context "with CDATA" do
|
69
69
|
before do
|
70
|
-
@
|
70
|
+
@xml = '<user><![CDATA[Erik Michaels-Ober]]></user>'
|
71
71
|
end
|
72
72
|
|
73
73
|
it "should parse correctly" do
|
74
|
-
MultiXml.parse(@
|
74
|
+
MultiXml.parse(@xml).should == {"user" => "Erik Michaels-Ober"}
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
78
|
context "with content" do
|
79
79
|
before do
|
80
|
-
@
|
80
|
+
@xml = '<user>Erik Michaels-Ober</user>'
|
81
81
|
end
|
82
82
|
|
83
83
|
it "should parse correctly" do
|
84
|
-
MultiXml.parse(@
|
84
|
+
MultiXml.parse(@xml).should == {"user" => "Erik Michaels-Ober"}
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
88
|
context "with an attribute" do
|
89
89
|
before do
|
90
|
-
@
|
90
|
+
@xml = '<user name="Erik Michaels-Ober"/>'
|
91
91
|
end
|
92
92
|
|
93
93
|
it "should parse correctly" do
|
94
|
-
MultiXml.parse(@
|
94
|
+
MultiXml.parse(@xml).should == {"user" => {"name" => "Erik Michaels-Ober"}}
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
98
|
context "with multiple attributes" do
|
99
99
|
before do
|
100
|
-
@
|
100
|
+
@xml = '<user name="Erik Michaels-Ober" screen_name="sferik"/>'
|
101
101
|
end
|
102
102
|
|
103
103
|
it "should parse correctly" do
|
104
|
-
MultiXml.parse(@
|
104
|
+
MultiXml.parse(@xml).should == {"user" => {"name" => "Erik Michaels-Ober", "screen_name" => "sferik"}}
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
108
|
context "with :symbolize_keys => true" do
|
109
109
|
before do
|
110
|
-
@
|
110
|
+
@xml = '<user name="Erik Michaels-Ober"/>'
|
111
111
|
end
|
112
112
|
|
113
113
|
it "should symbolize keys" do
|
114
|
-
MultiXml.parse(@
|
114
|
+
MultiXml.parse(@xml, :symbolize_keys => true).should == {:user => {:name => "Erik Michaels-Ober"}}
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
@@ -119,29 +119,29 @@ describe "MultiXml" do
|
|
119
119
|
%w(true false).each do |boolean|
|
120
120
|
context "when #{boolean}" do
|
121
121
|
it "should be #{boolean}" do
|
122
|
-
|
123
|
-
MultiXml.parse(
|
122
|
+
xml = "<tag type=\"boolean\">#{boolean}</tag>"
|
123
|
+
MultiXml.parse(xml)['tag'].should instance_eval("be_#{boolean}")
|
124
124
|
end
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
128
128
|
context "when 1" do
|
129
129
|
before do
|
130
|
-
@
|
130
|
+
@xml = '<tag type="boolean">1</tag>'
|
131
131
|
end
|
132
132
|
|
133
133
|
it "should be true" do
|
134
|
-
MultiXml.parse(@
|
134
|
+
MultiXml.parse(@xml)['tag'].should be_true
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
138
|
context "when 0" do
|
139
139
|
before do
|
140
|
-
@
|
140
|
+
@xml = '<tag type="boolean">0</tag>'
|
141
141
|
end
|
142
142
|
|
143
143
|
it "should be false" do
|
144
|
-
MultiXml.parse(@
|
144
|
+
MultiXml.parse(@xml)['tag'].should be_false
|
145
145
|
end
|
146
146
|
end
|
147
147
|
end
|
@@ -149,224 +149,213 @@ describe "MultiXml" do
|
|
149
149
|
context "with an attribute type=\"integer\"" do
|
150
150
|
context "with a positive integer" do
|
151
151
|
before do
|
152
|
-
@
|
152
|
+
@xml = '<tag type="integer">1</tag>'
|
153
153
|
end
|
154
154
|
|
155
155
|
it "should be a Fixnum" do
|
156
|
-
MultiXml.parse(@
|
156
|
+
MultiXml.parse(@xml)['tag'].should be_a(Fixnum)
|
157
157
|
end
|
158
158
|
|
159
159
|
it "should be the correct number" do
|
160
|
-
MultiXml.parse(@
|
160
|
+
MultiXml.parse(@xml)['tag'].should == 1
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
164
|
context "with a negative integer" do
|
165
165
|
before do
|
166
|
-
@
|
166
|
+
@xml = '<tag type="integer">-1</tag>'
|
167
167
|
end
|
168
168
|
|
169
169
|
it "should be a Fixnum" do
|
170
|
-
MultiXml.parse(@
|
170
|
+
MultiXml.parse(@xml)['tag'].should be_a(Fixnum)
|
171
171
|
end
|
172
172
|
|
173
173
|
it "should be the correct number" do
|
174
|
-
MultiXml.parse(@
|
174
|
+
MultiXml.parse(@xml)['tag'].should == -1
|
175
175
|
end
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
179
|
context "with an attribute type=\"string\"" do
|
180
180
|
before do
|
181
|
-
@
|
181
|
+
@xml = '<tag type="string"></tag>'
|
182
182
|
end
|
183
183
|
|
184
184
|
it "should be a String" do
|
185
|
-
MultiXml.parse(@
|
185
|
+
MultiXml.parse(@xml)['tag'].should be_a(String)
|
186
186
|
end
|
187
187
|
|
188
188
|
it "should be the correct string" do
|
189
|
-
MultiXml.parse(@
|
189
|
+
MultiXml.parse(@xml)['tag'].should == ""
|
190
190
|
end
|
191
191
|
end
|
192
192
|
|
193
193
|
context "with an attribute type=\"date\"" do
|
194
194
|
before do
|
195
|
-
@
|
195
|
+
@xml = '<tag type="date">1970-01-01</tag>'
|
196
196
|
end
|
197
197
|
|
198
198
|
it "should be a Date" do
|
199
|
-
MultiXml.parse(@
|
199
|
+
MultiXml.parse(@xml)['tag'].should be_a(Date)
|
200
200
|
end
|
201
201
|
|
202
202
|
it "should be the correct date" do
|
203
|
-
MultiXml.parse(@
|
203
|
+
MultiXml.parse(@xml)['tag'].should == Date.parse('1970-01-01')
|
204
204
|
end
|
205
205
|
end
|
206
206
|
|
207
207
|
context "with an attribute type=\"datetime\"" do
|
208
208
|
before do
|
209
|
-
@
|
209
|
+
@xml = '<tag type="datetime">1970-01-01 00:00</tag>'
|
210
210
|
end
|
211
211
|
|
212
212
|
it "should be a Time" do
|
213
|
-
MultiXml.parse(@
|
213
|
+
MultiXml.parse(@xml)['tag'].should be_a(Time)
|
214
214
|
end
|
215
215
|
|
216
216
|
it "should be the correct time" do
|
217
|
-
MultiXml.parse(@
|
217
|
+
MultiXml.parse(@xml)['tag'].should == Time.parse('1970-01-01 00:00')
|
218
218
|
end
|
219
219
|
end
|
220
220
|
|
221
221
|
context "with an attribute type=\"dateTime\"" do
|
222
222
|
before do
|
223
|
-
@
|
223
|
+
@xml = '<tag type="datetime">1970-01-01 00:00</tag>'
|
224
224
|
end
|
225
225
|
|
226
226
|
it "should be a Time" do
|
227
|
-
MultiXml.parse(@
|
227
|
+
MultiXml.parse(@xml)['tag'].should be_a(Time)
|
228
228
|
end
|
229
229
|
|
230
230
|
it "should be the correct time" do
|
231
|
-
MultiXml.parse(@
|
231
|
+
MultiXml.parse(@xml)['tag'].should == Time.parse('1970-01-01 00:00')
|
232
232
|
end
|
233
233
|
end
|
234
234
|
|
235
235
|
context "with an attribute type=\"double\"" do
|
236
236
|
before do
|
237
|
-
@
|
237
|
+
@xml = '<tag type="double">3.14159265358979</tag>'
|
238
238
|
end
|
239
239
|
|
240
240
|
it "should be a Float" do
|
241
|
-
MultiXml.parse(@
|
241
|
+
MultiXml.parse(@xml)['tag'].should be_a(Float)
|
242
242
|
end
|
243
243
|
|
244
244
|
it "should be the correct number" do
|
245
|
-
MultiXml.parse(@
|
245
|
+
MultiXml.parse(@xml)['tag'].should == 3.14159265358979
|
246
246
|
end
|
247
247
|
end
|
248
248
|
|
249
249
|
context "with an attribute type=\"decimal\"" do
|
250
250
|
before do
|
251
|
-
@
|
251
|
+
@xml = '<tag type="decimal">3.14159265358979323846264338327950288419716939937510</tag>'
|
252
252
|
end
|
253
253
|
|
254
254
|
it "should be a BigDecimal" do
|
255
|
-
MultiXml.parse(@
|
255
|
+
MultiXml.parse(@xml)['tag'].should be_a(BigDecimal)
|
256
256
|
end
|
257
257
|
|
258
258
|
it "should be the correct number" do
|
259
|
-
MultiXml.parse(@
|
259
|
+
MultiXml.parse(@xml)['tag'].should == 3.14159265358979323846264338327950288419716939937510
|
260
260
|
end
|
261
261
|
end
|
262
262
|
|
263
263
|
context "with an attribute type=\"base64Binary\"" do
|
264
264
|
before do
|
265
|
-
@
|
265
|
+
@xml = '<tag type="base64Binary">aW1hZ2UucG5n</tag>'
|
266
266
|
end
|
267
267
|
|
268
268
|
it "should be a String" do
|
269
|
-
MultiXml.parse(@
|
269
|
+
MultiXml.parse(@xml)['tag'].should be_a(String)
|
270
270
|
end
|
271
271
|
|
272
272
|
it "should be the correct string" do
|
273
|
-
MultiXml.parse(@
|
273
|
+
MultiXml.parse(@xml)['tag'].should == "image.png"
|
274
274
|
end
|
275
275
|
end
|
276
276
|
|
277
277
|
context "with an attribute type=\"yaml\"" do
|
278
278
|
before do
|
279
|
-
@
|
279
|
+
@xml = "<tag type=\"yaml\">--- \n1: should be an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n should_have_underscores: true\n</tag>"
|
280
280
|
end
|
281
281
|
|
282
282
|
it "should parse correctly" do
|
283
|
-
MultiXml.parse(@
|
283
|
+
MultiXml.parse(@xml)['tag'].should == {:message => "Have a nice day", 1 => "should be an integer", "array" => [{"should-have-dashes" => true, "should_have_underscores" => true}]}
|
284
284
|
end
|
285
285
|
end
|
286
286
|
|
287
287
|
context "with an attribute type=\"file\"" do
|
288
288
|
before do
|
289
|
-
@
|
289
|
+
@xml = '<tag type="file" name="data.txt" content_type="text/plain">ZGF0YQ==</tag>'
|
290
290
|
end
|
291
291
|
|
292
292
|
it "should be a StringIO" do
|
293
|
-
MultiXml.parse(@
|
293
|
+
MultiXml.parse(@xml)['tag'].should be_a(StringIO)
|
294
294
|
end
|
295
295
|
|
296
296
|
it "should be decoded correctly" do
|
297
|
-
MultiXml.parse(@
|
297
|
+
MultiXml.parse(@xml)['tag'].string.should == 'data'
|
298
298
|
end
|
299
299
|
|
300
300
|
it "should have the correct file name" do
|
301
|
-
MultiXml.parse(@
|
301
|
+
MultiXml.parse(@xml)['tag'].original_filename.should == 'data.txt'
|
302
302
|
end
|
303
303
|
|
304
304
|
it "should have the correct content type" do
|
305
|
-
MultiXml.parse(@
|
305
|
+
MultiXml.parse(@xml)['tag'].content_type.should == 'text/plain'
|
306
306
|
end
|
307
307
|
|
308
308
|
context "with missing name and content type" do
|
309
309
|
before do
|
310
|
-
@
|
310
|
+
@xml = '<tag type="file">ZGF0YQ==</tag>'
|
311
311
|
end
|
312
312
|
|
313
313
|
it "should be a StringIO" do
|
314
|
-
MultiXml.parse(@
|
314
|
+
MultiXml.parse(@xml)['tag'].should be_a(StringIO)
|
315
315
|
end
|
316
316
|
|
317
317
|
it "should be decoded correctly" do
|
318
|
-
MultiXml.parse(@
|
318
|
+
MultiXml.parse(@xml)['tag'].string.should == 'data'
|
319
319
|
end
|
320
320
|
|
321
321
|
it "should have the default file name" do
|
322
|
-
MultiXml.parse(@
|
322
|
+
MultiXml.parse(@xml)['tag'].original_filename.should == 'untitled'
|
323
323
|
end
|
324
324
|
|
325
325
|
it "should have the default content type" do
|
326
|
-
MultiXml.parse(@
|
326
|
+
MultiXml.parse(@xml)['tag'].content_type.should == 'application/octet-stream'
|
327
327
|
end
|
328
328
|
end
|
329
329
|
end
|
330
330
|
|
331
|
-
context "with an unrecognized attribute type" do
|
332
|
-
before do
|
333
|
-
@string = '<tag type="foo"/>'
|
334
|
-
end
|
335
|
-
|
336
|
-
it "should pass through the type" do
|
337
|
-
pending
|
338
|
-
MultiXml.parse(@string)['tag']['type'].should == 'foo'
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
331
|
%w(integer boolean date datetime yaml).each do |type|
|
343
332
|
context "with an empty attribute type=\"#{type}\"" do
|
344
333
|
before do
|
345
|
-
@
|
334
|
+
@xml = "<tag type=\"#{type}\"/>"
|
346
335
|
end
|
347
336
|
|
348
337
|
it "should be nil" do
|
349
|
-
MultiXml.parse(@
|
338
|
+
MultiXml.parse(@xml)['tag'].should be_nil
|
350
339
|
end
|
351
340
|
end
|
352
341
|
end
|
353
342
|
|
354
343
|
context "with an empty attribute type=\"array\"" do
|
355
344
|
before do
|
356
|
-
@
|
345
|
+
@xml = '<users type="array"/>'
|
357
346
|
end
|
358
347
|
|
359
348
|
it "should be an empty Array" do
|
360
|
-
MultiXml.parse(@
|
349
|
+
MultiXml.parse(@xml)['users'].should == []
|
361
350
|
end
|
362
351
|
|
363
352
|
context "with whitespace" do
|
364
353
|
before do
|
365
|
-
@
|
354
|
+
@xml = '<users type="array"> </users>'
|
366
355
|
end
|
367
356
|
|
368
357
|
it "should be an empty Array" do
|
369
|
-
MultiXml.parse(@
|
358
|
+
MultiXml.parse(@xml)['users'].should == []
|
370
359
|
end
|
371
360
|
end
|
372
361
|
end
|
@@ -385,8 +374,8 @@ describe "MultiXml" do
|
|
385
374
|
context "in content" do
|
386
375
|
it "should unescape XML entities" do
|
387
376
|
@xml_entities.each do |key, value|
|
388
|
-
|
389
|
-
MultiXml.parse(
|
377
|
+
xml = "<tag>#{value}</tag>"
|
378
|
+
MultiXml.parse(xml)['tag'].should == key
|
390
379
|
end
|
391
380
|
end
|
392
381
|
end
|
@@ -394,8 +383,8 @@ describe "MultiXml" do
|
|
394
383
|
context "in attribute" do
|
395
384
|
it "should unescape XML entities" do
|
396
385
|
@xml_entities.each do |key, value|
|
397
|
-
|
398
|
-
MultiXml.parse(
|
386
|
+
xml = "<tag attribute=\"#{value}\"/>"
|
387
|
+
MultiXml.parse(xml)['tag']['attribute'].should == key
|
399
388
|
end
|
400
389
|
end
|
401
390
|
end
|
@@ -403,21 +392,21 @@ describe "MultiXml" do
|
|
403
392
|
|
404
393
|
context "with dasherized tag" do
|
405
394
|
before do
|
406
|
-
@
|
395
|
+
@xml = '<tag-1/>'
|
407
396
|
end
|
408
397
|
|
409
398
|
it "should undasherize tag" do
|
410
|
-
MultiXml.parse(@
|
399
|
+
MultiXml.parse(@xml).keys.should include('tag_1')
|
411
400
|
end
|
412
401
|
end
|
413
402
|
|
414
403
|
context "with dasherized attribute" do
|
415
404
|
before do
|
416
|
-
@
|
405
|
+
@xml = '<tag attribute-1="1"></tag>'
|
417
406
|
end
|
418
407
|
|
419
408
|
it "should undasherize attribute" do
|
420
|
-
MultiXml.parse(@
|
409
|
+
MultiXml.parse(@xml)['tag'].keys.should include('attribute_1')
|
421
410
|
end
|
422
411
|
end
|
423
412
|
end
|
@@ -425,56 +414,80 @@ describe "MultiXml" do
|
|
425
414
|
context "a document" do
|
426
415
|
context "with :symbolize_keys => true" do
|
427
416
|
before do
|
428
|
-
@
|
417
|
+
@xml = '<user><name>Erik Michaels-Ober</name></user>'
|
429
418
|
end
|
430
419
|
|
431
420
|
it "should symbolize keys" do
|
432
|
-
MultiXml.parse(@
|
421
|
+
MultiXml.parse(@xml, :symbolize_keys => true).should == {:user => {:name => "Erik Michaels-Ober"}}
|
433
422
|
end
|
434
423
|
end
|
435
424
|
|
436
425
|
context "with children" do
|
437
426
|
before do
|
438
|
-
@
|
427
|
+
@xml = '<root><user name="Erik Michaels-Ober"/></root>'
|
439
428
|
end
|
440
429
|
|
441
430
|
it "should parse correctly" do
|
442
|
-
MultiXml.parse(@
|
431
|
+
MultiXml.parse(@xml).should == {"root" => {"user" => {"name"=>"Erik Michaels-Ober"}}}
|
443
432
|
end
|
444
433
|
|
445
434
|
context "with text" do
|
446
435
|
before do
|
447
|
-
@
|
436
|
+
@xml = '<user><name>Erik Michaels-Ober</name></user>'
|
437
|
+
end
|
438
|
+
|
439
|
+
it "should parse correctly" do
|
440
|
+
MultiXml.parse(@xml).should == {"user" => {"name" => "Erik Michaels-Ober"}}
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
context "with an unrecognized attribute type" do
|
445
|
+
before do
|
446
|
+
@xml = '<user type="admin"><name>Erik Michaels-Ober</name></user>'
|
447
|
+
end
|
448
|
+
|
449
|
+
it "should pass through the type" do
|
450
|
+
MultiXml.parse(@xml)['user']['type'].should == 'admin'
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
context "with newlines and whitespace" do
|
455
|
+
before do
|
456
|
+
@xml = <<-XML
|
457
|
+
<user>
|
458
|
+
<name>Erik Michaels-Ober</name>
|
459
|
+
</user>
|
460
|
+
XML
|
448
461
|
end
|
449
462
|
|
450
463
|
it "should parse correctly" do
|
451
|
-
MultiXml.parse(@
|
464
|
+
MultiXml.parse(@xml).should == {"user"=>{"name"=>"Erik Michaels-Ober"}}
|
452
465
|
end
|
453
466
|
end
|
454
467
|
|
455
468
|
# Babies having babies
|
456
469
|
context "with children" do
|
457
470
|
before do
|
458
|
-
@
|
471
|
+
@xml = '<root><user name="Erik Michaels-Ober"><status text="Hello"/></user></root>'
|
459
472
|
end
|
460
473
|
|
461
474
|
it "should parse correctly" do
|
462
|
-
MultiXml.parse(@
|
475
|
+
MultiXml.parse(@xml).should == {"root" => {"user" => {"name" => "Erik Michaels-Ober", "status" => {"text" => "Hello"}}}}
|
463
476
|
end
|
464
477
|
end
|
465
478
|
end
|
466
479
|
|
467
480
|
context "with sibling children" do
|
468
481
|
before do
|
469
|
-
@
|
482
|
+
@xml = '<root><users>Erik Michaels-Ober</users><users>Wynn Netherland</users></root>'
|
470
483
|
end
|
471
484
|
|
472
485
|
it "should parse correctly" do
|
473
|
-
MultiXml.parse(@
|
486
|
+
MultiXml.parse(@xml).should == {"root" => {"users" => ["Erik Michaels-Ober", "Wynn Netherland"]}}
|
474
487
|
end
|
475
488
|
|
476
|
-
it "should
|
477
|
-
MultiXml.parse(@
|
489
|
+
it "should be Array" do
|
490
|
+
MultiXml.parse(@xml)['root']['users'].should be_a(Array)
|
478
491
|
end
|
479
492
|
|
480
493
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: multi_xml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Erik Michaels-Ober
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-16 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -93,7 +93,7 @@ dependencies:
|
|
93
93
|
version: "2.0"
|
94
94
|
type: :development
|
95
95
|
version_requirements: *id005
|
96
|
-
description: A gem to provide swappable XML backends utilizing LibXML, Nokogiri,
|
96
|
+
description: A gem to provide swappable XML backends utilizing LibXML, Nokogiri, or REXML.
|
97
97
|
email:
|
98
98
|
- sferik@gmail.com
|
99
99
|
executables: []
|
@@ -111,6 +111,7 @@ files:
|
|
111
111
|
- README.rdoc
|
112
112
|
- Rakefile
|
113
113
|
- lib/multi_xml.rb
|
114
|
+
- lib/multi_xml/core_extensions.rb
|
114
115
|
- lib/multi_xml/parsers/libxml.rb
|
115
116
|
- lib/multi_xml/parsers/nokogiri.rb
|
116
117
|
- lib/multi_xml/parsers/rexml.rb
|
@@ -151,7 +152,7 @@ rubyforge_project: multi_xml
|
|
151
152
|
rubygems_version: 1.3.7
|
152
153
|
signing_key:
|
153
154
|
specification_version: 3
|
154
|
-
summary: A
|
155
|
+
summary: A generic swappable back-end for XML parsing
|
155
156
|
test_files:
|
156
157
|
- spec/multi_xml_spec.rb
|
157
158
|
- spec/spec_helper.rb
|