nori 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.travis.yml +3 -1
- data/CHANGELOG.md +4 -0
- data/lib/nori/core_ext/hash.rb +0 -15
- data/lib/nori/parser/nokogiri.rb +13 -1
- data/lib/nori/version.rb +1 -1
- data/lib/nori/xml_utility_node.rb +5 -3
- data/nori.gemspec +1 -0
- data/spec/nori/api_spec.rb +17 -17
- data/spec/nori/core_ext/hash_spec.rb +5 -35
- data/spec/nori/core_ext/object_spec.rb +2 -2
- data/spec/nori/core_ext/string_spec.rb +8 -8
- data/spec/nori/nori_spec.rb +82 -77
- metadata +17 -25
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5734d4c7a672d830ea4199339b869da468bc2eab
|
4
|
+
data.tar.gz: d590616887899c0c17739e95b4f46e64ba12a367
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ce4642320270373612e945d7912269e45541954ca9b1f163c81e9527333994aa6f1c2f289d11fc61c3768aea76dffcd3d64923f830e2439e995c2d305a6140e5
|
7
|
+
data.tar.gz: 0f3b03f4ffda5f874fd5a5780de08bbb891167351ea67c69d2f8b86f49e0a65f8b11582e0070343731398641afda5ae9b881f6ea308556f9ff1bdb98af3576b6
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/lib/nori/core_ext/hash.rb
CHANGED
@@ -4,21 +4,6 @@ class Nori
|
|
4
4
|
module CoreExt
|
5
5
|
module Hash
|
6
6
|
|
7
|
-
# @return <String> This hash as a query string
|
8
|
-
#
|
9
|
-
# @example
|
10
|
-
# { :name => "Bob",
|
11
|
-
# :address => {
|
12
|
-
# :street => '111 Ruby Ave.',
|
13
|
-
# :city => 'Ruby Central',
|
14
|
-
# :phones => ['111-111-1111', '222-222-2222']
|
15
|
-
# }
|
16
|
-
# }.to_params
|
17
|
-
# #=> "name=Bob&address[city]=Ruby Central&address[phones][]=111-111-1111&address[phones][]=222-222-2222&address[street]=111 Ruby Ave."
|
18
|
-
def to_params
|
19
|
-
map { |k, v| normalize_param(k,v) }.flatten.join('&')
|
20
|
-
end
|
21
|
-
|
22
7
|
# @param key<Object> The key for the param.
|
23
8
|
# @param value<Object> The value for the param.
|
24
9
|
#
|
data/lib/nori/parser/nokogiri.rb
CHANGED
@@ -19,15 +19,27 @@ class Nori
|
|
19
19
|
stack.push Nori::XMLUtilityNode.new(options, name, Hash[*attrs.flatten])
|
20
20
|
end
|
21
21
|
|
22
|
+
# To keep backward behaviour compatibility
|
23
|
+
# delete last child if it is a space-only text node
|
22
24
|
def end_element(name)
|
23
25
|
if stack.size > 1
|
24
26
|
last = stack.pop
|
27
|
+
maybe_string = last.children.last
|
28
|
+
if maybe_string.is_a?(String) and maybe_string.strip.empty?
|
29
|
+
last.children.pop
|
30
|
+
end
|
25
31
|
stack.last.add_node last
|
26
32
|
end
|
27
33
|
end
|
28
34
|
|
35
|
+
# If this node is a successive character then add it as is.
|
36
|
+
# First child being a space-only text node will not be added
|
37
|
+
# because there is no previous characters.
|
29
38
|
def characters(string)
|
30
|
-
|
39
|
+
last = stack.last
|
40
|
+
if last and last.children.last.is_a?(String) or string.strip.size > 0
|
41
|
+
last.add_node(string)
|
42
|
+
end
|
31
43
|
end
|
32
44
|
|
33
45
|
alias cdata_block characters
|
data/lib/nori/version.rb
CHANGED
@@ -24,10 +24,11 @@ class Nori
|
|
24
24
|
# 13:20:00-05:00 1:20 PM, US Eastern Standard Time
|
25
25
|
# 13:20:00+02:00 1:20 PM, Central European Standard Time
|
26
26
|
# 13:20:00Z 1:20 PM, Coordinated Universal Time (UTC)
|
27
|
+
# 13:20:30.5555Z 1:20 PM and 30.5555 seconds, Coordinated Universal Time (UTC)
|
27
28
|
# 00:00:00 midnight
|
28
29
|
# 24:00:00 midnight
|
29
30
|
|
30
|
-
XS_TIME = /^\d{2}:\d{2}:\d{2}[
|
31
|
+
XS_TIME = /^\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?$/
|
31
32
|
|
32
33
|
# Simple xs:date Regexp.
|
33
34
|
# Valid xs:date formats
|
@@ -38,7 +39,7 @@ class Nori
|
|
38
39
|
# 2004-04-12+02:00 April 12, 2004, Central European Summer Time, which is 2 hours ahead of Coordinated Universal Time (UTC)
|
39
40
|
# 2004-04-12Z April 12, 2004, Coordinated Universal Time (UTC)
|
40
41
|
|
41
|
-
XS_DATE =
|
42
|
+
XS_DATE = /^-?\d{4}-\d{2}-\d{2}(?:Z|[+-]\d{2}:?\d{2})?$/
|
42
43
|
|
43
44
|
# Simple xs:dateTime Regexp.
|
44
45
|
# Valid xs:dateTime formats
|
@@ -48,8 +49,9 @@ class Nori
|
|
48
49
|
# 2004-04-12T13:20:00+02:00 1:20 pm on April 12, 2004, Central European Summer Time
|
49
50
|
# 2004-04-12T13:20:15.5-05:00 1:20 pm and 15.5 seconds on April 12, 2004, US Eastern Standard Time
|
50
51
|
# 2004-04-12T13:20:00Z 1:20 pm on April 12, 2004, Coordinated Universal Time (UTC)
|
52
|
+
# 2004-04-12T13:20:15.5Z 1:20 pm and 15.5 seconds on April 12, 2004, Coordinated Universal Time (UTC)
|
51
53
|
|
52
|
-
XS_DATE_TIME =
|
54
|
+
XS_DATE_TIME = /^-?\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?$/
|
53
55
|
|
54
56
|
def self.typecasts
|
55
57
|
@@typecasts
|
data/nori.gemspec
CHANGED
data/spec/nori/api_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe Nori do
|
|
4
4
|
|
5
5
|
describe "PARSERS" do
|
6
6
|
it "should return a Hash of parser details" do
|
7
|
-
Nori::PARSERS.
|
7
|
+
expect(Nori::PARSERS).to eq({ :rexml => "REXML", :nokogiri => "Nokogiri" })
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -16,12 +16,12 @@ describe Nori do
|
|
16
16
|
</history>
|
17
17
|
XML
|
18
18
|
|
19
|
-
nori.parse(xml)["history"]["ns10:case"].
|
19
|
+
expect(nori.parse(xml)["history"]["ns10:case"]).to eq("a_case")
|
20
20
|
end
|
21
21
|
|
22
22
|
it "defaults to not change XML tags" do
|
23
23
|
xml = '<userResponse id="1"><accountStatus>active</accountStatus></userResponse>'
|
24
|
-
nori.parse(xml).
|
24
|
+
expect(nori.parse(xml)).to eq({ "userResponse" => { "@id" => "1", "accountStatus" => "active" } })
|
25
25
|
end
|
26
26
|
|
27
27
|
it "raises when passed unknown global options" do
|
@@ -33,7 +33,7 @@ describe Nori do
|
|
33
33
|
context ".new with :strip_namespaces" do
|
34
34
|
it "strips the namespace identifiers when set to true" do
|
35
35
|
xml = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"></soap:Envelope>'
|
36
|
-
nori(:strip_namespaces => true).parse(xml).
|
36
|
+
expect(nori(:strip_namespaces => true).parse(xml)).to have_key("Envelope")
|
37
37
|
end
|
38
38
|
|
39
39
|
it "still converts namespaced entries to array elements" do
|
@@ -47,7 +47,7 @@ describe Nori do
|
|
47
47
|
XML
|
48
48
|
|
49
49
|
expected = [{ "name" => "a_name" }, { "name" => "another_name" }]
|
50
|
-
nori(:strip_namespaces => true).parse(xml)["history"]["case"].
|
50
|
+
expect(nori(:strip_namespaces => true).parse(xml)["history"]["case"]).to eq(expected)
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
@@ -58,7 +58,7 @@ describe Nori do
|
|
58
58
|
snakecase_symbols = lambda { |tag| tag.snakecase.to_sym }
|
59
59
|
nori = nori(:convert_tags_to => snakecase_symbols)
|
60
60
|
|
61
|
-
nori.parse(xml).
|
61
|
+
expect(nori.parse(xml)).to eq({ :user_response => { :@id => "1", :account_status => "active" } })
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
@@ -98,29 +98,29 @@ describe Nori do
|
|
98
98
|
context "#parse" do
|
99
99
|
it "defaults to use advanced typecasting" do
|
100
100
|
hash = nori.parse("<value>true</value>")
|
101
|
-
hash["value"].
|
101
|
+
expect(hash["value"]).to eq(true)
|
102
102
|
end
|
103
103
|
|
104
104
|
it "defaults to use the Nokogiri parser" do
|
105
105
|
# parsers are loaded lazily by default
|
106
106
|
require "nori/parser/nokogiri"
|
107
107
|
|
108
|
-
Nori::Parser::Nokogiri.
|
108
|
+
expect(Nori::Parser::Nokogiri).to receive(:parse).and_return({})
|
109
109
|
nori.parse("<any>thing</any>")
|
110
110
|
end
|
111
111
|
|
112
112
|
it "strips the XML" do
|
113
113
|
xml = double("xml")
|
114
|
-
xml.
|
114
|
+
expect(xml).to receive(:strip).and_return("<any>thing</any>")
|
115
115
|
|
116
|
-
nori.parse(xml).
|
116
|
+
expect(nori.parse(xml)).to eq({ "any" => "thing" })
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
120
|
context "#parse without :advanced_typecasting" do
|
121
121
|
it "can be changed to not typecast too much" do
|
122
122
|
hash = nori(:advanced_typecasting => false).parse("<value>true</value>")
|
123
|
-
hash["value"].
|
123
|
+
expect(hash["value"]).to eq("true")
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
@@ -129,7 +129,7 @@ describe Nori do
|
|
129
129
|
# parsers are loaded lazily by default
|
130
130
|
require "nori/parser/rexml"
|
131
131
|
|
132
|
-
Nori::Parser::REXML.
|
132
|
+
expect(Nori::Parser::REXML).to receive(:parse).and_return({})
|
133
133
|
nori(:parser => :rexml).parse("<any>thing</any>")
|
134
134
|
end
|
135
135
|
end
|
@@ -138,13 +138,13 @@ describe Nori do
|
|
138
138
|
it "can be changed to not delete xmlns attributes" do
|
139
139
|
xml = '<userResponse xmlns="http://schema.company.com/some/path/to/namespace/v1"><accountStatus>active</accountStatus></userResponse>'
|
140
140
|
hash = nori(:delete_namespace_attributes => false).parse(xml)
|
141
|
-
hash.
|
141
|
+
expect(hash).to eq({"userResponse" => {"@xmlns" => "http://schema.company.com/some/path/to/namespace/v1", "accountStatus" => "active"}})
|
142
142
|
end
|
143
143
|
|
144
144
|
it "can be changed to not delete xsi attributes" do
|
145
145
|
xml = '<userResponse xsi="abc:myType"><accountStatus>active</accountStatus></userResponse>'
|
146
146
|
hash = nori(:delete_namespace_attributes => false).parse(xml)
|
147
|
-
hash.
|
147
|
+
expect(hash).to eq({"userResponse" => {"@xsi" => "abc:myType", "accountStatus" => "active"}})
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
@@ -152,13 +152,13 @@ describe Nori do
|
|
152
152
|
it "can be changed to delete xmlns attributes" do
|
153
153
|
xml = '<userResponse xmlns="http://schema.company.com/some/path/to/namespace/v1"><accountStatus>active</accountStatus></userResponse>'
|
154
154
|
hash = nori(:delete_namespace_attributes => true).parse(xml)
|
155
|
-
hash.
|
155
|
+
expect(hash).to eq({"userResponse" => {"accountStatus" => "active"}})
|
156
156
|
end
|
157
157
|
|
158
158
|
it "can be changed to delete xsi attributes" do
|
159
159
|
xml = '<userResponse xsi="abc:myType"><accountStatus>active</accountStatus></userResponse>'
|
160
160
|
hash = nori(:delete_namespace_attributes => true).parse(xml)
|
161
|
-
hash.
|
161
|
+
expect(hash).to eq({"userResponse" => {"accountStatus" => "active"}})
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
@@ -166,7 +166,7 @@ describe Nori do
|
|
166
166
|
it "can be configured to skip dash to underscope conversion" do
|
167
167
|
xml = '<any-tag>foo bar</any-tag'
|
168
168
|
hash = nori(:convert_dashes_to_underscores => false).parse(xml)
|
169
|
-
hash.
|
169
|
+
expect(hash).to eq({'any-tag' => 'foo bar'})
|
170
170
|
end
|
171
171
|
end
|
172
172
|
|
@@ -2,36 +2,6 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Hash do
|
4
4
|
|
5
|
-
describe "#to_params" do
|
6
|
-
|
7
|
-
{
|
8
|
-
{ "foo" => "bar", "baz" => "bat" } => "foo=bar&baz=bat",
|
9
|
-
{ "foo" => [ "bar", "baz" ] } => "foo[]=bar&foo[]=baz",
|
10
|
-
{ "foo" => [ {"bar" => "1"}, {"bar" => 2} ] } => "foo[][bar]=1&foo[][bar]=2",
|
11
|
-
{ "foo" => { "bar" => [ {"baz" => 1}, {"baz" => "2"} ] } } => "foo[bar][][baz]=1&foo[bar][][baz]=2",
|
12
|
-
{ "foo" => {"1" => "bar", "2" => "baz"} } => "foo[1]=bar&foo[2]=baz"
|
13
|
-
}.each do |hash, params|
|
14
|
-
it "should covert hash: #{hash.inspect} to params: #{params.inspect}" do
|
15
|
-
hash.to_params.split('&').sort.should == params.split('&').sort
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should not leave a trailing &" do
|
20
|
-
{
|
21
|
-
:name => 'Bob',
|
22
|
-
:address => {
|
23
|
-
:street => '111 Ruby Ave.',
|
24
|
-
:city => 'Ruby Central',
|
25
|
-
:phones => ['111-111-1111', '222-222-2222']
|
26
|
-
}
|
27
|
-
}.to_params.should_not =~ /&$/
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should URL encode unsafe characters" do
|
31
|
-
{:q => "?&\" +"}.to_params.should == "q=%3F%26%22%20%2B"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
5
|
describe "#normalize_param" do
|
36
6
|
it "should have specs"
|
37
7
|
end
|
@@ -40,8 +10,8 @@ describe Hash do
|
|
40
10
|
|
41
11
|
it "should turn the hash into xml attributes" do
|
42
12
|
attrs = { :one => "ONE", "two" => "TWO" }.to_xml_attributes
|
43
|
-
attrs.
|
44
|
-
attrs.
|
13
|
+
expect(attrs).to match(/one="ONE"/m)
|
14
|
+
expect(attrs).to match(/two="TWO"/m)
|
45
15
|
end
|
46
16
|
|
47
17
|
it "should preserve _ in hash keys" do
|
@@ -51,9 +21,9 @@ describe Hash do
|
|
51
21
|
:merb => "uses extlib"
|
52
22
|
}.to_xml_attributes
|
53
23
|
|
54
|
-
attrs.
|
55
|
-
attrs.
|
56
|
-
attrs.
|
24
|
+
expect(attrs).to match(/some_long_attribute="with short value"/)
|
25
|
+
expect(attrs).to match(/merb="uses extlib"/)
|
26
|
+
expect(attrs).to match(/crash="burn"/)
|
57
27
|
end
|
58
28
|
end
|
59
29
|
|
@@ -5,13 +5,13 @@ describe Object do
|
|
5
5
|
describe "#blank?" do
|
6
6
|
[nil, false, [], {}].each do |object|
|
7
7
|
it "should return true for: #{object.inspect}" do
|
8
|
-
object.blank
|
8
|
+
expect(object.blank?).to be_true
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
12
|
[true, [nil], 1, "string", { :key => "value" }].each do |object|
|
13
13
|
it "should return false for: #{object.inspect}" do
|
14
|
-
object.blank
|
14
|
+
expect(object.blank?).to be_false
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -4,29 +4,29 @@ describe String do
|
|
4
4
|
|
5
5
|
describe "#snakecase" do
|
6
6
|
it "lowercases one word CamelCase" do
|
7
|
-
"Merb".snakecase.
|
7
|
+
expect("Merb".snakecase).to eq("merb")
|
8
8
|
end
|
9
9
|
|
10
10
|
it "makes one underscore snakecase two word CamelCase" do
|
11
|
-
"MerbCore".snakecase.
|
11
|
+
expect("MerbCore".snakecase).to eq("merb_core")
|
12
12
|
end
|
13
13
|
|
14
14
|
it "handles CamelCase with more than 2 words" do
|
15
|
-
"SoYouWantContributeToMerbCore".snakecase.
|
15
|
+
expect("SoYouWantContributeToMerbCore".snakecase).to eq("so_you_want_contribute_to_merb_core")
|
16
16
|
end
|
17
17
|
|
18
18
|
it "handles CamelCase with more than 2 capital letter in a row" do
|
19
|
-
"CNN".snakecase.
|
20
|
-
"CNNNews".snakecase.
|
21
|
-
"HeadlineCNNNews".snakecase.
|
19
|
+
expect("CNN".snakecase).to eq("cnn")
|
20
|
+
expect("CNNNews".snakecase).to eq("cnn_news")
|
21
|
+
expect("HeadlineCNNNews".snakecase).to eq("headline_cnn_news")
|
22
22
|
end
|
23
23
|
|
24
24
|
it "does NOT change one word lowercase" do
|
25
|
-
"merb".snakecase.
|
25
|
+
expect("merb".snakecase).to eq("merb")
|
26
26
|
end
|
27
27
|
|
28
28
|
it "leaves snake_case as is" do
|
29
|
-
"merb_core".snakecase.
|
29
|
+
expect("merb_core".snakecase).to eq("merb_core")
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
data/spec/nori/nori_spec.rb
CHANGED
@@ -9,12 +9,12 @@ describe Nori do
|
|
9
9
|
|
10
10
|
it "should work with unnormalized characters" do
|
11
11
|
xml = '<root>&</root>'
|
12
|
-
parse(xml).
|
12
|
+
expect(parse(xml)).to eq({ 'root' => "&" })
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should transform a simple tag with content" do
|
16
16
|
xml = "<tag>This is the contents</tag>"
|
17
|
-
parse(xml).
|
17
|
+
expect(parse(xml)).to eq({ 'tag' => 'This is the contents' })
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should work with cdata tags" do
|
@@ -25,13 +25,13 @@ describe Nori do
|
|
25
25
|
]]>
|
26
26
|
</tag>
|
27
27
|
END
|
28
|
-
parse(xml)["tag"].strip.
|
28
|
+
expect(parse(xml)["tag"].strip).to eq("text inside cdata")
|
29
29
|
end
|
30
30
|
|
31
31
|
it "should transform a simple tag with attributes" do
|
32
32
|
xml = "<tag attr1='1' attr2='2'></tag>"
|
33
33
|
hash = { 'tag' => { '@attr1' => '1', '@attr2' => '2' } }
|
34
|
-
parse(xml).
|
34
|
+
expect(parse(xml)).to eq(hash)
|
35
35
|
end
|
36
36
|
|
37
37
|
it "should transform repeating siblings into an array" do
|
@@ -42,7 +42,7 @@ describe Nori do
|
|
42
42
|
</opt>
|
43
43
|
XML
|
44
44
|
|
45
|
-
parse(xml)['opt']['user'].class.
|
45
|
+
expect(parse(xml)['opt']['user'].class).to eq(Array)
|
46
46
|
|
47
47
|
hash = {
|
48
48
|
'opt' => {
|
@@ -56,7 +56,7 @@ describe Nori do
|
|
56
56
|
}
|
57
57
|
}
|
58
58
|
|
59
|
-
parse(xml).
|
59
|
+
expect(parse(xml)).to eq(hash)
|
60
60
|
end
|
61
61
|
|
62
62
|
it "should not transform non-repeating siblings into an array" do
|
@@ -66,7 +66,7 @@ describe Nori do
|
|
66
66
|
</opt>
|
67
67
|
XML
|
68
68
|
|
69
|
-
parse(xml)['opt']['user'].class.
|
69
|
+
expect(parse(xml)['opt']['user'].class).to eq(Hash)
|
70
70
|
|
71
71
|
hash = {
|
72
72
|
'opt' => {
|
@@ -77,7 +77,7 @@ describe Nori do
|
|
77
77
|
}
|
78
78
|
}
|
79
79
|
|
80
|
-
parse(xml).
|
80
|
+
expect(parse(xml)).to eq(hash)
|
81
81
|
end
|
82
82
|
|
83
83
|
it "should prefix attributes with an @-sign to avoid problems with overwritten values" do
|
@@ -88,96 +88,101 @@ describe Nori do
|
|
88
88
|
</multiRef>
|
89
89
|
XML
|
90
90
|
|
91
|
-
parse(xml)["multiRef"].
|
91
|
+
expect(parse(xml)["multiRef"]).to eq({ "login" => "grep", "@id" => "id1", "id" => "76737" })
|
92
92
|
end
|
93
93
|
|
94
94
|
context "without advanced typecasting" do
|
95
95
|
it "should not transform 'true'" do
|
96
96
|
hash = parse("<value>true</value>", :advanced_typecasting => false)
|
97
|
-
hash["value"].
|
97
|
+
expect(hash["value"]).to eq("true")
|
98
98
|
end
|
99
99
|
|
100
100
|
it "should not transform 'false'" do
|
101
101
|
hash = parse("<value>false</value>", :advanced_typecasting => false)
|
102
|
-
hash["value"].
|
102
|
+
expect(hash["value"]).to eq("false")
|
103
103
|
end
|
104
104
|
|
105
105
|
it "should not transform Strings matching the xs:time format" do
|
106
106
|
hash = parse("<value>09:33:55Z</value>", :advanced_typecasting => false)
|
107
|
-
hash["value"].
|
107
|
+
expect(hash["value"]).to eq("09:33:55Z")
|
108
108
|
end
|
109
109
|
|
110
110
|
it "should not transform Strings matching the xs:date format" do
|
111
111
|
hash = parse("<value>1955-04-18-05:00</value>", :advanced_typecasting => false)
|
112
|
-
hash["value"].
|
112
|
+
expect(hash["value"]).to eq("1955-04-18-05:00")
|
113
113
|
end
|
114
114
|
|
115
115
|
it "should not transform Strings matching the xs:dateTime format" do
|
116
116
|
hash = parse("<value>1955-04-18T11:22:33-05:00</value>", :advanced_typecasting => false)
|
117
|
-
hash["value"].
|
117
|
+
expect(hash["value"]).to eq("1955-04-18T11:22:33-05:00")
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
121
121
|
context "with advanced typecasting" do
|
122
122
|
it "should transform 'true' to TrueClass" do
|
123
|
-
parse("<value>true</value>")["value"].
|
123
|
+
expect(parse("<value>true</value>")["value"]).to eq(true)
|
124
124
|
end
|
125
125
|
|
126
126
|
it "should transform 'false' to FalseClass" do
|
127
|
-
parse("<value>false</value>")["value"].
|
127
|
+
expect(parse("<value>false</value>")["value"]).to eq(false)
|
128
128
|
end
|
129
129
|
|
130
130
|
it "should transform Strings matching the xs:time format to Time objects" do
|
131
|
-
parse("<value>09:33:
|
131
|
+
expect(parse("<value>09:33:55.7Z</value>")["value"]).to eq(Time.parse("09:33:55.7Z"))
|
132
132
|
end
|
133
133
|
|
134
134
|
it "should transform Strings matching the xs:time format ahead of utc to Time objects" do
|
135
|
-
parse("<value>09:33:55+02:00</value>")["value"].
|
135
|
+
expect(parse("<value>09:33:55+02:00</value>")["value"]).to eq(Time.parse("09:33:55+02:00"))
|
136
136
|
end
|
137
137
|
|
138
138
|
it "should transform Strings matching the xs:date format to Date objects" do
|
139
|
-
parse("<value>1955-04-18-05:00</value>")["value"].
|
139
|
+
expect(parse("<value>1955-04-18-05:00</value>")["value"]).to eq(Date.parse("1955-04-18-05:00"))
|
140
140
|
end
|
141
141
|
|
142
142
|
it "should transform Strings matching the xs:dateTime format ahead of utc to Date objects" do
|
143
|
-
parse("<value>1955-04-18+02:00</value>")["value"].
|
143
|
+
expect(parse("<value>1955-04-18+02:00</value>")["value"]).to eq(Date.parse("1955-04-18+02:00"))
|
144
144
|
end
|
145
145
|
|
146
146
|
it "should transform Strings matching the xs:dateTime format to DateTime objects" do
|
147
|
-
parse("<value>1955-04-18T11:22:33
|
148
|
-
DateTime.parse("1955-04-18T11:22:33
|
147
|
+
expect(parse("<value>1955-04-18T11:22:33.5Z</value>")["value"]).to eq(
|
148
|
+
DateTime.parse("1955-04-18T11:22:33.5Z")
|
149
|
+
)
|
149
150
|
end
|
150
151
|
|
151
152
|
it "should transform Strings matching the xs:dateTime format ahead of utc to DateTime objects" do
|
152
|
-
parse("<value>1955-04-18T11:22:33+02:00</value>")["value"].
|
153
|
+
expect(parse("<value>1955-04-18T11:22:33+02:00</value>")["value"]).to eq(
|
153
154
|
DateTime.parse("1955-04-18T11:22:33+02:00")
|
155
|
+
)
|
154
156
|
end
|
155
157
|
|
156
158
|
it "should transform Strings matching the xs:dateTime format with seconds and an offset to DateTime objects" do
|
157
|
-
parse("<value>2004-04-12T13:20:15.5-05:00</value>")["value"].
|
159
|
+
expect(parse("<value>2004-04-12T13:20:15.5-05:00</value>")["value"]).to eq(
|
158
160
|
DateTime.parse("2004-04-12T13:20:15.5-05:00")
|
161
|
+
)
|
159
162
|
end
|
160
163
|
|
161
164
|
it "should not transform Strings containing an xs:time String and more" do
|
162
|
-
parse("<value>09:33:55Z is a time</value>")["value"].
|
163
|
-
parse("<value>09:33:55Z_is_a_file_name</value>")["value"].
|
165
|
+
expect(parse("<value>09:33:55Z is a time</value>")["value"]).to eq("09:33:55Z is a time")
|
166
|
+
expect(parse("<value>09:33:55Z_is_a_file_name</value>")["value"]).to eq("09:33:55Z_is_a_file_name")
|
164
167
|
end
|
165
168
|
|
166
169
|
it "should not transform Strings containing an xs:date String and more" do
|
167
|
-
parse("<value>1955-04-18-05:00 is a date</value>")["value"].
|
168
|
-
parse("<value>1955-04-18-05:00_is_a_file_name</value>")["value"].
|
170
|
+
expect(parse("<value>1955-04-18-05:00 is a date</value>")["value"]).to eq("1955-04-18-05:00 is a date")
|
171
|
+
expect(parse("<value>1955-04-18-05:00_is_a_file_name</value>")["value"]).to eq("1955-04-18-05:00_is_a_file_name")
|
169
172
|
end
|
170
173
|
|
171
174
|
it "should not transform Strings containing an xs:dateTime String and more" do
|
172
|
-
parse("<value>1955-04-18T11:22:33-05:00 is a dateTime</value>")["value"].
|
175
|
+
expect(parse("<value>1955-04-18T11:22:33-05:00 is a dateTime</value>")["value"]).to eq(
|
173
176
|
"1955-04-18T11:22:33-05:00 is a dateTime"
|
174
|
-
|
177
|
+
)
|
178
|
+
expect(parse("<value>1955-04-18T11:22:33-05:00_is_a_file_name</value>")["value"]).to eq(
|
175
179
|
"1955-04-18T11:22:33-05:00_is_a_file_name"
|
180
|
+
)
|
176
181
|
end
|
177
182
|
|
178
183
|
["00-00-00", "0000-00-00", "0000-00-00T00:00:00", "0569-23-0141", "DS2001-19-1312654773", "e6:53:01:00:ce:b4:06"].each do |date_string|
|
179
184
|
it "should not transform a String like '#{date_string}' to date or time" do
|
180
|
-
parse("<value>#{date_string}</value>")["value"].
|
185
|
+
expect(parse("<value>#{date_string}</value>")["value"]).to eq(date_string)
|
181
186
|
end
|
182
187
|
end
|
183
188
|
end
|
@@ -194,59 +199,59 @@ describe Nori do
|
|
194
199
|
end
|
195
200
|
|
196
201
|
it "correctly parse text nodes" do
|
197
|
-
@data.
|
202
|
+
expect(@data).to eq({
|
198
203
|
'opt' => {
|
199
204
|
'user' => [
|
200
205
|
'Gary R Epstein',
|
201
206
|
'Simon T Tyson'
|
202
207
|
]
|
203
208
|
}
|
204
|
-
}
|
209
|
+
})
|
205
210
|
end
|
206
211
|
|
207
|
-
it "
|
208
|
-
@data['opt']['user'][0].attributes.
|
212
|
+
it "parses attributes for text node if present" do
|
213
|
+
expect(@data['opt']['user'][0].attributes).to eq({'login' => 'grep'})
|
209
214
|
end
|
210
215
|
|
211
216
|
it "default attributes to empty hash if not present" do
|
212
|
-
@data['opt']['user'][1].attributes.
|
217
|
+
expect(@data['opt']['user'][1].attributes).to eq({})
|
213
218
|
end
|
214
219
|
|
215
220
|
it "add 'attributes' accessor methods to parsed instances of String" do
|
216
|
-
@data['opt']['user'][0].
|
217
|
-
@data['opt']['user'][0].
|
221
|
+
expect(@data['opt']['user'][0]).to respond_to(:attributes)
|
222
|
+
expect(@data['opt']['user'][0]).to respond_to(:attributes=)
|
218
223
|
end
|
219
224
|
|
220
225
|
it "not add 'attributes' accessor methods to all instances of String" do
|
221
|
-
"some-string".
|
222
|
-
"some-string".
|
226
|
+
expect("some-string").not_to respond_to(:attributes)
|
227
|
+
expect("some-string").not_to respond_to(:attributes=)
|
223
228
|
end
|
224
229
|
end
|
225
230
|
|
226
231
|
it "should typecast an integer" do
|
227
232
|
xml = "<tag type='integer'>10</tag>"
|
228
|
-
parse(xml)['tag'].
|
233
|
+
expect(parse(xml)['tag']).to eq(10)
|
229
234
|
end
|
230
235
|
|
231
236
|
it "should typecast a true boolean" do
|
232
237
|
xml = "<tag type='boolean'>true</tag>"
|
233
|
-
parse(xml)['tag'].
|
238
|
+
expect(parse(xml)['tag']).to be(true)
|
234
239
|
end
|
235
240
|
|
236
241
|
it "should typecast a false boolean" do
|
237
242
|
["false"].each do |w|
|
238
|
-
parse("<tag type='boolean'>#{w}</tag>")['tag'].
|
243
|
+
expect(parse("<tag type='boolean'>#{w}</tag>")['tag']).to be(false)
|
239
244
|
end
|
240
245
|
end
|
241
246
|
|
242
247
|
it "should typecast a datetime" do
|
243
248
|
xml = "<tag type='datetime'>2007-12-31 10:32</tag>"
|
244
|
-
parse(xml)['tag'].
|
249
|
+
expect(parse(xml)['tag']).to eq(Time.parse( '2007-12-31 10:32' ).utc)
|
245
250
|
end
|
246
251
|
|
247
252
|
it "should typecast a date" do
|
248
253
|
xml = "<tag type='date'>2007-12-31</tag>"
|
249
|
-
parse(xml)['tag'].
|
254
|
+
expect(parse(xml)['tag']).to eq(Date.parse('2007-12-31'))
|
250
255
|
end
|
251
256
|
|
252
257
|
xml_entities = {
|
@@ -260,51 +265,51 @@ describe Nori do
|
|
260
265
|
it "should unescape html entities" do
|
261
266
|
xml_entities.each do |k,v|
|
262
267
|
xml = "<tag>Some content #{v}</tag>"
|
263
|
-
parse(xml)['tag'].
|
268
|
+
expect(parse(xml)['tag']).to match(Regexp.new(k))
|
264
269
|
end
|
265
270
|
end
|
266
271
|
|
267
272
|
it "should unescape XML entities in attributes" do
|
268
273
|
xml_entities.each do |key, value|
|
269
274
|
xml = "<tag attr='Some content #{value}'></tag>"
|
270
|
-
parse(xml)['tag']['@attr'].
|
275
|
+
expect(parse(xml)['tag']['@attr']).to match(Regexp.new(key))
|
271
276
|
end
|
272
277
|
end
|
273
278
|
|
274
279
|
it "should undasherize keys as tags" do
|
275
280
|
xml = "<tag-1>Stuff</tag-1>"
|
276
|
-
parse(xml).keys.
|
281
|
+
expect(parse(xml).keys).to include('tag_1')
|
277
282
|
end
|
278
283
|
|
279
284
|
it "should undasherize keys as attributes" do
|
280
285
|
xml = "<tag1 attr-1='1'></tag1>"
|
281
|
-
parse(xml)['tag1'].keys.
|
286
|
+
expect(parse(xml)['tag1'].keys).to include('@attr_1')
|
282
287
|
end
|
283
288
|
|
284
289
|
it "should undasherize keys as tags and attributes" do
|
285
290
|
xml = "<tag-1 attr-1='1'></tag-1>"
|
286
|
-
parse(xml).keys.
|
287
|
-
parse(xml)['tag_1'].keys.
|
291
|
+
expect(parse(xml).keys).to include('tag_1')
|
292
|
+
expect(parse(xml)['tag_1'].keys).to include('@attr_1')
|
288
293
|
end
|
289
294
|
|
290
295
|
it "should render nested content correctly" do
|
291
296
|
xml = "<root><tag1>Tag1 Content <em><strong>This is strong</strong></em></tag1></root>"
|
292
|
-
parse(xml)['root']['tag1'].
|
297
|
+
expect(parse(xml)['root']['tag1']).to eq("Tag1 Content <em><strong>This is strong</strong></em>")
|
293
298
|
end
|
294
299
|
|
295
|
-
it "should render nested content with
|
300
|
+
it "should render nested content with text nodes correctly" do
|
296
301
|
xml = "<root>Tag1 Content<em>Stuff</em> Hi There</root>"
|
297
|
-
parse(xml)['root'].
|
302
|
+
expect(parse(xml)['root']).to eq("Tag1 Content<em>Stuff</em> Hi There")
|
298
303
|
end
|
299
304
|
|
300
305
|
it "should ignore attributes when a child is a text node" do
|
301
306
|
xml = "<root attr1='1'>Stuff</root>"
|
302
|
-
parse(xml).
|
307
|
+
expect(parse(xml)).to eq({ "root" => "Stuff" })
|
303
308
|
end
|
304
309
|
|
305
310
|
it "should ignore attributes when any child is a text node" do
|
306
311
|
xml = "<root attr1='1'>Stuff <em>in italics</em></root>"
|
307
|
-
parse(xml).
|
312
|
+
expect(parse(xml)).to eq({ "root" => "Stuff <em>in italics</em>" })
|
308
313
|
end
|
309
314
|
|
310
315
|
it "should correctly transform multiple children" do
|
@@ -329,7 +334,7 @@ describe Nori do
|
|
329
334
|
}
|
330
335
|
}
|
331
336
|
|
332
|
-
parse(xml).
|
337
|
+
expect(parse(xml)).to eq(hash)
|
333
338
|
end
|
334
339
|
|
335
340
|
it "should properly handle nil values (ActiveSupport Compatible)" do
|
@@ -359,7 +364,7 @@ describe Nori do
|
|
359
364
|
'nil_true' => nil,
|
360
365
|
'namespaced' => nil
|
361
366
|
}
|
362
|
-
parse(topic_xml)["topic"].
|
367
|
+
expect(parse(topic_xml)["topic"]).to eq(expected_topic_hash)
|
363
368
|
end
|
364
369
|
|
365
370
|
it "should handle a single record from xml (ActiveSupport Compatible)" do
|
@@ -404,7 +409,7 @@ describe Nori do
|
|
404
409
|
}
|
405
410
|
|
406
411
|
parse(topic_xml)["topic"].each do |k,v|
|
407
|
-
v.
|
412
|
+
expect(v).to eq(expected_topic_hash[k])
|
408
413
|
end
|
409
414
|
end
|
410
415
|
|
@@ -456,7 +461,7 @@ describe Nori do
|
|
456
461
|
|
457
462
|
# puts Nori.parse(topics_xml)['topics'].first.inspect
|
458
463
|
parse(topics_xml)["topics"].first.each do |k,v|
|
459
|
-
v.
|
464
|
+
expect(v).to eq(expected_topic_hash[k])
|
460
465
|
end
|
461
466
|
end
|
462
467
|
|
@@ -467,7 +472,7 @@ describe Nori do
|
|
467
472
|
<user name="value"><age>21</age></user>
|
468
473
|
XML
|
469
474
|
|
470
|
-
parse(xml, :convert_attributes_to => converter).
|
475
|
+
expect(parse(xml, :convert_attributes_to => converter)).to eq({'user' => {'@name_k' => 'value_v', 'age' => '21'}})
|
471
476
|
end
|
472
477
|
end
|
473
478
|
|
@@ -492,7 +497,7 @@ describe Nori do
|
|
492
497
|
}
|
493
498
|
|
494
499
|
parse(topic_xml)["rsp"]["photos"]["photo"].each do |k, v|
|
495
|
-
v.
|
500
|
+
expect(v).to eq(expected_topic_hash[k])
|
496
501
|
end
|
497
502
|
end
|
498
503
|
|
@@ -503,7 +508,7 @@ describe Nori do
|
|
503
508
|
</blog>
|
504
509
|
XML
|
505
510
|
expected_blog_hash = {"blog" => {"posts" => []}}
|
506
|
-
parse(blog_xml).
|
511
|
+
expect(parse(blog_xml)).to eq(expected_blog_hash)
|
507
512
|
end
|
508
513
|
|
509
514
|
it "should handle empty array with whitespace from xml (ActiveSupport Compatible)" do
|
@@ -514,7 +519,7 @@ describe Nori do
|
|
514
519
|
</blog>
|
515
520
|
XML
|
516
521
|
expected_blog_hash = {"blog" => {"posts" => []}}
|
517
|
-
parse(blog_xml).
|
522
|
+
expect(parse(blog_xml)).to eq(expected_blog_hash)
|
518
523
|
end
|
519
524
|
|
520
525
|
it "should handle array with one entry from_xml (ActiveSupport Compatible)" do
|
@@ -526,7 +531,7 @@ describe Nori do
|
|
526
531
|
</blog>
|
527
532
|
XML
|
528
533
|
expected_blog_hash = {"blog" => {"posts" => ["a post"]}}
|
529
|
-
parse(blog_xml).
|
534
|
+
expect(parse(blog_xml)).to eq(expected_blog_hash)
|
530
535
|
end
|
531
536
|
|
532
537
|
it "should handle array with multiple entries from xml (ActiveSupport Compatible)" do
|
@@ -539,7 +544,7 @@ describe Nori do
|
|
539
544
|
</blog>
|
540
545
|
XML
|
541
546
|
expected_blog_hash = {"blog" => {"posts" => ["a post", "another post"]}}
|
542
|
-
parse(blog_xml).
|
547
|
+
expect(parse(blog_xml)).to eq(expected_blog_hash)
|
543
548
|
end
|
544
549
|
|
545
550
|
it "should handle file types (ActiveSupport Compatible)" do
|
@@ -550,12 +555,12 @@ describe Nori do
|
|
550
555
|
</blog>
|
551
556
|
XML
|
552
557
|
hash = parse(blog_xml)
|
553
|
-
hash.keys.
|
554
|
-
hash['blog'].keys.
|
558
|
+
expect(hash.keys).to include('blog')
|
559
|
+
expect(hash['blog'].keys).to include('logo')
|
555
560
|
|
556
561
|
file = hash['blog']['logo']
|
557
|
-
file.original_filename.
|
558
|
-
file.content_type.
|
562
|
+
expect(file.original_filename).to eq('logo.png')
|
563
|
+
expect(file.content_type).to eq('image/png')
|
559
564
|
end
|
560
565
|
|
561
566
|
it "should handle file from xml with defaults (ActiveSupport Compatible)" do
|
@@ -566,8 +571,8 @@ describe Nori do
|
|
566
571
|
</blog>
|
567
572
|
XML
|
568
573
|
file = parse(blog_xml)['blog']['logo']
|
569
|
-
file.original_filename.
|
570
|
-
file.content_type.
|
574
|
+
expect(file.original_filename).to eq('untitled')
|
575
|
+
expect(file.content_type).to eq('application/octet-stream')
|
571
576
|
end
|
572
577
|
|
573
578
|
it "should handle xsd like types from xml (ActiveSupport Compatible)" do
|
@@ -591,7 +596,7 @@ describe Nori do
|
|
591
596
|
'illustration' => "babe.png"
|
592
597
|
}
|
593
598
|
|
594
|
-
parse(bacon_xml)["bacon"].
|
599
|
+
expect(parse(bacon_xml)["bacon"]).to eq(expected_bacon_hash)
|
595
600
|
end
|
596
601
|
|
597
602
|
it "should let type trickle through when unknown (ActiveSupport Compatible)" do
|
@@ -608,7 +613,7 @@ describe Nori do
|
|
608
613
|
'image' => {'@type' => 'ProductImage', 'filename' => 'image.gif' },
|
609
614
|
}
|
610
615
|
|
611
|
-
parse(product_xml)["product"].
|
616
|
+
expect(parse(product_xml)["product"]).to eq(expected_product_hash)
|
612
617
|
end
|
613
618
|
|
614
619
|
it "should handle unescaping from xml (ActiveResource Compatible)" do
|
@@ -618,16 +623,16 @@ describe Nori do
|
|
618
623
|
'pre_escaped_string' => 'First & Last Name'
|
619
624
|
}
|
620
625
|
|
621
|
-
parse(xml_string)['person'].
|
626
|
+
expect(parse(xml_string)['person']).to eq(expected_hash)
|
622
627
|
end
|
623
628
|
|
624
629
|
it "handle an empty xml string" do
|
625
|
-
parse('').
|
630
|
+
expect(parse('')).to eq({})
|
626
631
|
end
|
627
632
|
|
628
633
|
# As returned in the response body by the unfuddle XML API when creating objects
|
629
634
|
it "handle an xml string containing a single space" do
|
630
|
-
parse(' ').
|
635
|
+
expect(parse(' ')).to eq({})
|
631
636
|
end
|
632
637
|
|
633
638
|
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nori
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
5
|
-
prerelease:
|
4
|
+
version: 2.5.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Daniel Harrington
|
@@ -11,54 +10,48 @@ authors:
|
|
11
10
|
autorequire:
|
12
11
|
bindir: bin
|
13
12
|
cert_chain: []
|
14
|
-
date:
|
13
|
+
date: 2015-04-01 00:00:00.000000000 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: rake
|
18
17
|
requirement: !ruby/object:Gem::Requirement
|
19
|
-
none: false
|
20
18
|
requirements:
|
21
|
-
- - ~>
|
19
|
+
- - "~>"
|
22
20
|
- !ruby/object:Gem::Version
|
23
21
|
version: '10.0'
|
24
22
|
type: :development
|
25
23
|
prerelease: false
|
26
24
|
version_requirements: !ruby/object:Gem::Requirement
|
27
|
-
none: false
|
28
25
|
requirements:
|
29
|
-
- - ~>
|
26
|
+
- - "~>"
|
30
27
|
- !ruby/object:Gem::Version
|
31
28
|
version: '10.0'
|
32
29
|
- !ruby/object:Gem::Dependency
|
33
30
|
name: nokogiri
|
34
31
|
requirement: !ruby/object:Gem::Requirement
|
35
|
-
none: false
|
36
32
|
requirements:
|
37
|
-
- -
|
33
|
+
- - ">="
|
38
34
|
- !ruby/object:Gem::Version
|
39
35
|
version: 1.4.0
|
40
36
|
type: :development
|
41
37
|
prerelease: false
|
42
38
|
version_requirements: !ruby/object:Gem::Requirement
|
43
|
-
none: false
|
44
39
|
requirements:
|
45
|
-
- -
|
40
|
+
- - ">="
|
46
41
|
- !ruby/object:Gem::Version
|
47
42
|
version: 1.4.0
|
48
43
|
- !ruby/object:Gem::Dependency
|
49
44
|
name: rspec
|
50
45
|
requirement: !ruby/object:Gem::Requirement
|
51
|
-
none: false
|
52
46
|
requirements:
|
53
|
-
- - ~>
|
47
|
+
- - "~>"
|
54
48
|
- !ruby/object:Gem::Version
|
55
49
|
version: '2.12'
|
56
50
|
type: :development
|
57
51
|
prerelease: false
|
58
52
|
version_requirements: !ruby/object:Gem::Requirement
|
59
|
-
none: false
|
60
53
|
requirements:
|
61
|
-
- - ~>
|
54
|
+
- - "~>"
|
62
55
|
- !ruby/object:Gem::Version
|
63
56
|
version: '2.12'
|
64
57
|
description: XML to Hash translator
|
@@ -67,9 +60,9 @@ executables: []
|
|
67
60
|
extensions: []
|
68
61
|
extra_rdoc_files: []
|
69
62
|
files:
|
70
|
-
- .gitignore
|
71
|
-
- .rspec
|
72
|
-
- .travis.yml
|
63
|
+
- ".gitignore"
|
64
|
+
- ".rspec"
|
65
|
+
- ".travis.yml"
|
73
66
|
- CHANGELOG.md
|
74
67
|
- Gemfile
|
75
68
|
- LICENSE
|
@@ -98,27 +91,26 @@ files:
|
|
98
91
|
homepage: https://github.com/savonrb/nori
|
99
92
|
licenses:
|
100
93
|
- MIT
|
94
|
+
metadata: {}
|
101
95
|
post_install_message:
|
102
96
|
rdoc_options: []
|
103
97
|
require_paths:
|
104
98
|
- lib
|
105
99
|
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
100
|
requirements:
|
108
|
-
- -
|
101
|
+
- - ">="
|
109
102
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
103
|
+
version: 1.9.2
|
111
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
-
none: false
|
113
105
|
requirements:
|
114
|
-
- -
|
106
|
+
- - ">="
|
115
107
|
- !ruby/object:Gem::Version
|
116
108
|
version: '0'
|
117
109
|
requirements: []
|
118
110
|
rubyforge_project: nori
|
119
|
-
rubygems_version:
|
111
|
+
rubygems_version: 2.2.2
|
120
112
|
signing_key:
|
121
|
-
specification_version:
|
113
|
+
specification_version: 4
|
122
114
|
summary: XML to Hash translator
|
123
115
|
test_files:
|
124
116
|
- spec/nori/api_spec.rb
|