apricoteatsgorilla 0.5.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/README.rdoc +54 -0
- data/Rakefile +43 -0
- data/VERSION +1 -0
- data/apricoteatsgorilla.gemspec +64 -0
- data/lib/apricoteatsgorilla.rb +3 -0
- data/lib/apricoteatsgorilla/apricoteatsgorilla.rb +324 -0
- data/lib/apricoteatsgorilla/xml_node.rb +78 -0
- data/spec/apricoteatsgorilla/apricoteatsgorilla_spec.rb +35 -0
- data/spec/apricoteatsgorilla/hash_to_xml_spec.rb +78 -0
- data/spec/apricoteatsgorilla/soap_envelope_spec.rb +44 -0
- data/spec/apricoteatsgorilla/xml_node_spec.rb +80 -0
- data/spec/apricoteatsgorilla/xml_to_hash_spec.rb +90 -0
- data/spec/spec_helper.rb +20 -0
- metadata +98 -0
data/README.rdoc
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
= Apricot eats Gorilla
|
2
|
+
|
3
|
+
Apricot eats Gorilla is a SOAP communication helper. It translates between
|
4
|
+
SOAP messages (XML) and Ruby Hashes and comes with some additional helpers
|
5
|
+
for working with SOAP services.
|
6
|
+
|
7
|
+
== Install
|
8
|
+
|
9
|
+
$ gem install rubiii-apricoteatsgorilla -s http://gems.github.com
|
10
|
+
|
11
|
+
== Dependencies
|
12
|
+
|
13
|
+
hpricot 0.8.241 (the latest JRuby-compatible version)
|
14
|
+
|
15
|
+
Also available at: {GitHub Downloads}[http://github.com/rubiii/apricoteatsgorilla/downloads]
|
16
|
+
|
17
|
+
== Translate an XML String into a Ruby Hash
|
18
|
+
|
19
|
+
xml = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
20
|
+
<soap:Body>
|
21
|
+
<ns2:authenticateResponse xmlns:ns2="http://v1_0.ws.example.com/">
|
22
|
+
<return>
|
23
|
+
<apricot>
|
24
|
+
<eats>Gorilla</eats>
|
25
|
+
</apricot>
|
26
|
+
</return>
|
27
|
+
</ns2:authenticateResponse>
|
28
|
+
</soap:Body>
|
29
|
+
</soap:Envelope>'
|
30
|
+
|
31
|
+
ApricotEatsGorilla[xml, "//return"]
|
32
|
+
# => { :apricot => { :eats => "Gorilla" } }
|
33
|
+
|
34
|
+
== Translate a Ruby Hash into an XML String
|
35
|
+
|
36
|
+
hash = { :apricot => { :eats => "Gorilla" } }
|
37
|
+
|
38
|
+
ApricotEatsGorilla[hash]
|
39
|
+
# => "<apricot><eats>Gorilla</eats></apricot>"
|
40
|
+
|
41
|
+
== Build a SOAP request envelope
|
42
|
+
|
43
|
+
ApricotEatsGorilla.soap_envelope { "<apricot><eats>Gorilla</eats></apricot>" }
|
44
|
+
|
45
|
+
# => '<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
46
|
+
# => <env:Body>
|
47
|
+
# => <apricot><eats>Gorilla</eats></apricot>
|
48
|
+
# => </env:Body>
|
49
|
+
# => </env:Envelope>'
|
50
|
+
|
51
|
+
== Read more
|
52
|
+
|
53
|
+
For more detailed information, please take a look at the
|
54
|
+
{GitHub Wiki}[http://wiki.github.com/rubiii/apricoteatsgorilla].
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake"
|
3
|
+
require "spec/rake/spectask"
|
4
|
+
require "rake/rdoctask"
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
Spec::Rake::SpecTask.new do |spec|
|
9
|
+
spec.spec_files = FileList["spec/**/*_spec.rb"]
|
10
|
+
spec.spec_opts << "--color"
|
11
|
+
end
|
12
|
+
|
13
|
+
Rake::RDocTask.new do |rdoc|
|
14
|
+
rdoc.title = "Apricot eats Gorilla"
|
15
|
+
rdoc.rdoc_dir = "rdoc"
|
16
|
+
rdoc.main = "README.rdoc"
|
17
|
+
rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
18
|
+
rdoc.options = ["--line-numbers", "--inline-source"]
|
19
|
+
end
|
20
|
+
|
21
|
+
begin
|
22
|
+
require "jeweler"
|
23
|
+
Jeweler::Tasks.new do |spec|
|
24
|
+
spec.name = "apricoteatsgorilla"
|
25
|
+
spec.author = "Daniel Harrington"
|
26
|
+
spec.email = "me@rubiii.com"
|
27
|
+
spec.homepage = "http://github.com/rubiii/apricoteatsgorilla"
|
28
|
+
spec.summary = "SOAP communication helper"
|
29
|
+
spec.description = spec.summary
|
30
|
+
|
31
|
+
spec.rdoc_options += [
|
32
|
+
"--title", "Apricot eats Gorilla",
|
33
|
+
"--main", "README.rdoc",
|
34
|
+
"--line-numbers",
|
35
|
+
"--inline-source"
|
36
|
+
]
|
37
|
+
|
38
|
+
spec.add_runtime_dependency("hpricot", "0.8.241")
|
39
|
+
spec.add_development_dependency("rspec", ">= 1.2.8")
|
40
|
+
end
|
41
|
+
rescue LoadError
|
42
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
43
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.9
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{apricoteatsgorilla}
|
8
|
+
s.version = "0.5.9"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Daniel Harrington"]
|
12
|
+
s.date = %q{2009-10-06}
|
13
|
+
s.description = %q{SOAP communication helper}
|
14
|
+
s.email = %q{me@rubiii.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"README.rdoc",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"apricoteatsgorilla.gemspec",
|
24
|
+
"lib/apricoteatsgorilla.rb",
|
25
|
+
"lib/apricoteatsgorilla/apricoteatsgorilla.rb",
|
26
|
+
"lib/apricoteatsgorilla/xml_node.rb",
|
27
|
+
"spec/apricoteatsgorilla/apricoteatsgorilla_spec.rb",
|
28
|
+
"spec/apricoteatsgorilla/hash_to_xml_spec.rb",
|
29
|
+
"spec/apricoteatsgorilla/soap_envelope_spec.rb",
|
30
|
+
"spec/apricoteatsgorilla/xml_node_spec.rb",
|
31
|
+
"spec/apricoteatsgorilla/xml_to_hash_spec.rb",
|
32
|
+
"spec/spec_helper.rb"
|
33
|
+
]
|
34
|
+
s.has_rdoc = true
|
35
|
+
s.homepage = %q{http://github.com/rubiii/apricoteatsgorilla}
|
36
|
+
s.rdoc_options = ["--charset=UTF-8", "--title", "Apricot eats Gorilla", "--main", "README.rdoc", "--line-numbers", "--inline-source"]
|
37
|
+
s.require_paths = ["lib"]
|
38
|
+
s.rubygems_version = %q{1.3.1}
|
39
|
+
s.summary = %q{SOAP communication helper}
|
40
|
+
s.test_files = [
|
41
|
+
"spec/apricoteatsgorilla/apricoteatsgorilla_spec.rb",
|
42
|
+
"spec/apricoteatsgorilla/hash_to_xml_spec.rb",
|
43
|
+
"spec/apricoteatsgorilla/soap_envelope_spec.rb",
|
44
|
+
"spec/apricoteatsgorilla/xml_node_spec.rb",
|
45
|
+
"spec/apricoteatsgorilla/xml_to_hash_spec.rb",
|
46
|
+
"spec/spec_helper.rb"
|
47
|
+
]
|
48
|
+
|
49
|
+
if s.respond_to? :specification_version then
|
50
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
51
|
+
s.specification_version = 2
|
52
|
+
|
53
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
54
|
+
s.add_runtime_dependency(%q<hpricot>, ["= 0.8.241"])
|
55
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.8"])
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<hpricot>, ["= 0.8.241"])
|
58
|
+
s.add_dependency(%q<rspec>, [">= 1.2.8"])
|
59
|
+
end
|
60
|
+
else
|
61
|
+
s.add_dependency(%q<hpricot>, ["= 0.8.241"])
|
62
|
+
s.add_dependency(%q<rspec>, [">= 1.2.8"])
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,324 @@
|
|
1
|
+
%w(digest/sha1 rubygems hpricot).each do |gem|
|
2
|
+
require gem
|
3
|
+
end
|
4
|
+
|
5
|
+
# == ApricotEatsGorilla
|
6
|
+
#
|
7
|
+
# Apricot eats Gorilla is a SOAP communication helper. It translates between
|
8
|
+
# SOAP messages (XML) and Ruby Hashes and comes with some additional helpers
|
9
|
+
# for working with SOAP services.
|
10
|
+
class ApricotEatsGorilla
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# SOAP dateTime format.
|
14
|
+
SOAPDateTimeFormat = "%Y-%m-%dT%H:%M:%S"
|
15
|
+
|
16
|
+
# SOAP dateTime Regexp.
|
17
|
+
SOAPDateTimeRegexp = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/
|
18
|
+
|
19
|
+
# SOAP namespaces by SOAP version.
|
20
|
+
SOAPNamespace = {
|
21
|
+
1 => "http://schemas.xmlsoap.org/soap/envelope/",
|
22
|
+
2 => "http://www.w3.org/2003/05/soap-envelope"
|
23
|
+
}
|
24
|
+
|
25
|
+
# Namespace for WS Security Secext
|
26
|
+
WSENamespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
|
27
|
+
|
28
|
+
# Namespace for WS Security Utility
|
29
|
+
WSUNamespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
|
30
|
+
|
31
|
+
# Flag to enable sorting of Hash keys.
|
32
|
+
attr_accessor :sort_keys
|
33
|
+
|
34
|
+
# Flag to disable conversion of XML tags to lowerCamelCase.
|
35
|
+
attr_accessor :disable_tag_names_to_lower_camel_case
|
36
|
+
|
37
|
+
# Flag to disable conversion of Hash keys to snake_case.
|
38
|
+
attr_accessor :disable_hash_keys_to_snake_case
|
39
|
+
|
40
|
+
# Flag to disable conversion of Hash keys to Symbols.
|
41
|
+
attr_accessor :disable_hash_keys_to_symbols
|
42
|
+
|
43
|
+
# Hash of namespaces (keys) and XML nodes (values) to apply these
|
44
|
+
# namespaces to.
|
45
|
+
attr_accessor :nodes_to_namespace
|
46
|
+
|
47
|
+
# Shortcut method for translating between XML Strings and Ruby Hashes.
|
48
|
+
# Delegates to +xml_to_hash+ in case +source+ is a String or delegates
|
49
|
+
# to +hash_to_xml+ in case +source+ is a Hash. Returns nil otherwise.
|
50
|
+
def [](source, root_node = nil)
|
51
|
+
case source
|
52
|
+
when String
|
53
|
+
xml_to_hash(source, root_node)
|
54
|
+
when Hash
|
55
|
+
hash_to_xml(source)
|
56
|
+
else
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Yields this class to a given +block+ for wrapping the setup of multiple
|
62
|
+
# flags at once.
|
63
|
+
def setup
|
64
|
+
yield self if block_given?
|
65
|
+
end
|
66
|
+
|
67
|
+
# Translates a given +xml+ String into a Ruby Hash.
|
68
|
+
#
|
69
|
+
# Starts parsing at the XML root node by default. Accepts an optional
|
70
|
+
# +root_node+ parameter for defining a custom root node to start parsing
|
71
|
+
# at using an XPath-Expression (Hpricot search).
|
72
|
+
#
|
73
|
+
# Notice that both namespaces and attributes get removed and the root node
|
74
|
+
# itself won't be included in the Hash.
|
75
|
+
#
|
76
|
+
# ==== Examples
|
77
|
+
#
|
78
|
+
# xml = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
79
|
+
# <soap:Body>
|
80
|
+
# <ns2:authenticateResponse xmlns:ns2="http://v1_0.ws.example.com/">
|
81
|
+
# <return>
|
82
|
+
# <apricot>
|
83
|
+
# <eats>Gorilla</eats>
|
84
|
+
# </apricot>
|
85
|
+
# </return>
|
86
|
+
# </ns2:authenticateResponse>
|
87
|
+
# </soap:Body>
|
88
|
+
# </soap:Envelope>'
|
89
|
+
#
|
90
|
+
# ApricotEatsGorilla.xml_to_hash(xml)
|
91
|
+
# # => { :body => { :authenticate_response => { :return => { :apricot => { :eats => "Gorilla" } } } } }
|
92
|
+
#
|
93
|
+
# ApricotEatsGorilla.xml_to_hash(xml, "//return")
|
94
|
+
# # => { :apricot => { :eats => "Gorilla" } }
|
95
|
+
def xml_to_hash(xml, root_node = nil)
|
96
|
+
doc = Hpricot.XML remove_whitespace(xml)
|
97
|
+
root = root_node ? doc.search(root_node) : doc.root
|
98
|
+
|
99
|
+
return nil if root.nil? || (root.respond_to?(:size) && root.size == 0)
|
100
|
+
if !root.respond_to? :each
|
101
|
+
xml_node_to_hash(root)
|
102
|
+
elsif root.size == 1
|
103
|
+
single_xml_root_node_to_hash(root)
|
104
|
+
else
|
105
|
+
multiple_xml_root_nodes_to_hash(root)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Translates a given Ruby +hash+ into an XML String.
|
110
|
+
#
|
111
|
+
# ==== Examples
|
112
|
+
#
|
113
|
+
# hash = { :apricot => { :eats => "Gorilla" } }
|
114
|
+
# ApricotEatsGorilla.hash_to_xml(hash)
|
115
|
+
#
|
116
|
+
# # => "<apricot><eats>Gorilla</eats></apricot>"
|
117
|
+
#
|
118
|
+
# hash = { :apricot => { :eats => ["Gorillas", "Snakes"] } }
|
119
|
+
# ApricotEatsGorilla.hash_to_xml(hash)
|
120
|
+
#
|
121
|
+
# # => "<apricot><eats>Gorillas</eats><eats>Snakes</eats></apricot>"
|
122
|
+
def hash_to_xml(hash)
|
123
|
+
nested_data_to_xml(hash.keys.first, hash.values.first)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Builds a SOAP request envelope and includes the content of a given
|
127
|
+
# +block+ into the envelope body. Accepts a Hash of additional +namespaces+
|
128
|
+
# to set. Also accepts an optional +version+ to specify the SOAP envelope
|
129
|
+
# namespace to use by SOAP version.
|
130
|
+
#
|
131
|
+
# ==== Examples
|
132
|
+
#
|
133
|
+
# ApricotEatsGorilla.soap_envelope do
|
134
|
+
# "<apricot><eats>Gorilla</eats></apricot>"
|
135
|
+
# end
|
136
|
+
#
|
137
|
+
# # => '<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
138
|
+
# # => <env:Body>
|
139
|
+
# # => <apricot><eats>Gorilla</eats></apricot>
|
140
|
+
# # => </env:Body>
|
141
|
+
# # => </env:Envelope>'
|
142
|
+
#
|
143
|
+
# ApricotEatsGorilla.soap_envelope(:wsdl => "http://example.com") { "pureText" }
|
144
|
+
#
|
145
|
+
# # => '<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://example.com">
|
146
|
+
# # => <env:Body>
|
147
|
+
# # => pureText
|
148
|
+
# # => </env:Body>
|
149
|
+
# # => </env:Envelope>'
|
150
|
+
def soap_envelope(namespaces = {}, wsse = {}, version = 1)
|
151
|
+
namespaces[:env] ||= SOAPNamespace[version] if SOAPNamespace[version]
|
152
|
+
|
153
|
+
header = xml_node("env:Header") { soap_header(wsse) }
|
154
|
+
body = xml_node("env:Body") { (yield if block_given?) || nil }
|
155
|
+
|
156
|
+
xml_node("env:Envelope", namespaces) { header + body }
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def soap_header(wsse)
|
162
|
+
return nil if !wsse || wsse.empty?
|
163
|
+
|
164
|
+
now = Time.now
|
165
|
+
xml_node("wsse:Security", :wsse => WSENamespace) do
|
166
|
+
xml_node("wsse:UsernameToken", :wsu => WSUNamespace) do
|
167
|
+
xml_node("wsse:Username") { wsse[:username] } <<
|
168
|
+
xml_node("wsse:Password") { wsse[:password] } <<
|
169
|
+
xml_node("wsse:Nonce") { wsse_nonce(now) } <<
|
170
|
+
xml_node("wsu:Created") { now.strftime(SOAPDateTimeFormat) }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Returns a random WSSE nonce.
|
176
|
+
def wsse_nonce(now = nil)
|
177
|
+
now ||= Time.now
|
178
|
+
Digest::SHA1.hexdigest(random_string + now.to_i.to_s)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Returns a random string of a certain +length+.
|
182
|
+
def random_string(length = 20)
|
183
|
+
(0...length).map { ("a".."z").to_a[rand(26)] }.join
|
184
|
+
end
|
185
|
+
|
186
|
+
# Translates a single XML root node to a Ruby Hash.
|
187
|
+
def single_xml_root_node_to_hash(root)
|
188
|
+
if root.first.children.nil?
|
189
|
+
{}
|
190
|
+
elsif root.first.children.first.kind_of? Hpricot::Text
|
191
|
+
map_xml_value(root.first.children.to_s)
|
192
|
+
else
|
193
|
+
xml_node_to_hash(root.first)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Translates multiple XML root nodes to a Ruby Hash.
|
198
|
+
def multiple_xml_root_nodes_to_hash(root)
|
199
|
+
root.map do |node|
|
200
|
+
if node.children.first.kind_of? Hpricot::Text
|
201
|
+
map_xml_value(node.children.to_s)
|
202
|
+
else
|
203
|
+
xml_node_to_hash(node)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Iterates through a given Hpricot +element+ and returns a Ruby Hash
|
209
|
+
# equal to the XML content of the given element.
|
210
|
+
def xml_node_to_hash(element)
|
211
|
+
hash = {}
|
212
|
+
|
213
|
+
element.each_child do |child|
|
214
|
+
key = create_hash_key(child.name)
|
215
|
+
value = create_hash_value(child)
|
216
|
+
|
217
|
+
case hash[key]
|
218
|
+
when Array
|
219
|
+
hash[key] << value
|
220
|
+
when nil
|
221
|
+
hash[key] = value
|
222
|
+
else
|
223
|
+
hash[key] = [ hash[key].dup, value ]
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
hash
|
228
|
+
end
|
229
|
+
|
230
|
+
# Returns a Hash key for +xml_node_to_hash+ by a given +name+.
|
231
|
+
def create_hash_key(name)
|
232
|
+
key = XMLNode.new(name)
|
233
|
+
key.strip_namespace!
|
234
|
+
key.to_snake_case! unless disable_hash_keys_to_snake_case
|
235
|
+
key = disable_hash_keys_to_symbols ? key.to_s : key.to_sym
|
236
|
+
end
|
237
|
+
|
238
|
+
# Returns a Hash value for +xml_node_to_hash+ by a given +value+.
|
239
|
+
def create_hash_value(value)
|
240
|
+
if value.children.nil? || value.children.empty?
|
241
|
+
nil
|
242
|
+
elsif value.children.size == 1 && value.children.first.text?
|
243
|
+
map_xml_value(value.children.first.to_html)
|
244
|
+
else
|
245
|
+
xml_node_to_hash(value)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# Expects a Hash +key+ and a Hash +value+. Iterates through the given Hash
|
250
|
+
# +value+ and returns an XML String of the given Hash structure.
|
251
|
+
def nested_data_to_xml(key, value)
|
252
|
+
case value
|
253
|
+
when Array
|
254
|
+
value.map { |subitem| nested_data_to_xml(key, subitem) }.join
|
255
|
+
when Hash
|
256
|
+
xml_node(key) do
|
257
|
+
sort_hash_keys(value).map do |subkey, subvalue|
|
258
|
+
case subvalue
|
259
|
+
when Array
|
260
|
+
subvalue.map { |subitem| nested_data_to_xml(subkey, subitem) }.join
|
261
|
+
when Hash
|
262
|
+
nested_data_to_xml(subkey, subvalue)
|
263
|
+
else
|
264
|
+
xml_node(subkey) { map_hash_value(subvalue) } if map_hash_value(subvalue)
|
265
|
+
end
|
266
|
+
end.join
|
267
|
+
end
|
268
|
+
else
|
269
|
+
xml_node(key) { map_hash_value(value) } if map_hash_value(value)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
# Returns an XML tag with a given +name+. Accepts a +block+ for tag content.
|
274
|
+
# Defaults to returning an empty-element tag in case no block was given.
|
275
|
+
# Also accepts a Hash of +attributes+ to be added to the XML tag.
|
276
|
+
def xml_node(name, attributes = {})
|
277
|
+
node = XMLNode.new(name.to_s)
|
278
|
+
node.to_lower_camel_case! unless disable_tag_names_to_lower_camel_case
|
279
|
+
node.namespace_from_hash!(nodes_to_namespace)
|
280
|
+
node.attributes = sort_hash_keys(attributes)
|
281
|
+
node.body = yield if block_given?
|
282
|
+
node.to_tag
|
283
|
+
end
|
284
|
+
|
285
|
+
# Removes whitespace between tags of a given +xml+ String.
|
286
|
+
def remove_whitespace(xml)
|
287
|
+
xml.gsub(/(>)\s*(<)/, '\1\2')
|
288
|
+
end
|
289
|
+
|
290
|
+
# Converts XML values to more natural Ruby objects.
|
291
|
+
def map_xml_value(value)
|
292
|
+
case value
|
293
|
+
when SOAPDateTimeRegexp
|
294
|
+
DateTime.parse(value)
|
295
|
+
when "true"
|
296
|
+
true
|
297
|
+
when "false"
|
298
|
+
false
|
299
|
+
else
|
300
|
+
value
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# Converts Hash values into valid XML values.
|
305
|
+
def map_hash_value(value)
|
306
|
+
if value.kind_of? DateTime
|
307
|
+
value.strftime(SOAPDateTimeFormat)
|
308
|
+
elsif !value.kind_of?(String) && value.respond_to?(:to_datetime)
|
309
|
+
value.to_datetime.strftime(SOAPDateTimeFormat)
|
310
|
+
elsif value.respond_to? :to_s
|
311
|
+
value.to_s
|
312
|
+
else
|
313
|
+
nil
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
# Returns a sorted version of a given +hash+ if +sort_keys+ is enabled.
|
318
|
+
def sort_hash_keys(hash)
|
319
|
+
return hash unless sort_keys
|
320
|
+
hash.keys.sort_by { |key| key.to_s }.map { |key| [ key, hash[key] ] }
|
321
|
+
end
|
322
|
+
|
323
|
+
end
|
324
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# == XMLNode
|
2
|
+
#
|
3
|
+
# Representation of an XML node. Inherits from String and includes some
|
4
|
+
# useful XML-specific methods for namespaces, attributes, node content etc.
|
5
|
+
class XMLNode < String
|
6
|
+
|
7
|
+
# Hash of attributes.
|
8
|
+
attr_writer :attributes
|
9
|
+
|
10
|
+
# Node body content.
|
11
|
+
attr_writer :body
|
12
|
+
|
13
|
+
# Strips the namespace from this node.
|
14
|
+
def strip_namespace!
|
15
|
+
sub!(/.+:(.+)/, '\1')
|
16
|
+
end
|
17
|
+
|
18
|
+
# Converts this node to snake_case.
|
19
|
+
def to_snake_case!
|
20
|
+
gsub!(/[A-Z]/, '_\0')
|
21
|
+
gsub!(/^_/, '')
|
22
|
+
downcase!
|
23
|
+
end
|
24
|
+
|
25
|
+
# Converts this node to lowerCamelCase.
|
26
|
+
def to_lower_camel_case!
|
27
|
+
gsub!(/_(.)/) { $1.upcase }
|
28
|
+
end
|
29
|
+
|
30
|
+
# Checks if this node is included in a given Hash of +namespaces+ and
|
31
|
+
# sets the namespace for this node in case it was found in the Hash.
|
32
|
+
def namespace_from_hash!(namespaces)
|
33
|
+
if namespaces && !namespaces.empty?
|
34
|
+
namespaces.each { |ns, nodes| @namespace = ns if self_included? nodes }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns this node as an XML tag including a namespace, attributes
|
39
|
+
# and a body in case these values were supplied.
|
40
|
+
def to_tag
|
41
|
+
if @body
|
42
|
+
"<#{namespace}#{self}#{attributes}>#{body}</#{namespace}#{self}>"
|
43
|
+
else
|
44
|
+
"<#{namespace}#{self}#{attributes} />"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Returns +true+ if self as a String or a Symbol is included in a
|
51
|
+
# given +array+. Returns +false+ otherwise.
|
52
|
+
def self_included?(array)
|
53
|
+
array.include?(self.to_s) || array.include?(self.to_sym)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns the namespace of this node. Defaults to an empty String
|
57
|
+
# in case no namespace was defined.
|
58
|
+
def namespace
|
59
|
+
@namespace ? "#{@namespace}:" : ""
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the attributes of this node. Defaults to an empty String
|
63
|
+
# in case no attributes were defined.
|
64
|
+
def attributes
|
65
|
+
if @attributes
|
66
|
+
@attributes.map { |key, value| %Q( xmlns:#{key}="#{value}") }
|
67
|
+
else
|
68
|
+
""
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns the body of this node. Defaults to an empty String in case
|
73
|
+
# no body was defined.
|
74
|
+
def body
|
75
|
+
@body ? @body : ""
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper")
|
2
|
+
|
3
|
+
describe ApricotEatsGorilla do
|
4
|
+
include SpecHelper
|
5
|
+
|
6
|
+
# setup
|
7
|
+
describe "setup" do
|
8
|
+
it "yields self to a given block" do
|
9
|
+
ApricotEatsGorilla.setup do |yielded|
|
10
|
+
yielded.should == ApricotEatsGorilla
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# []
|
16
|
+
describe "[]" do
|
17
|
+
before { reset_library_options }
|
18
|
+
|
19
|
+
it "converts a given XML into a Hash" do
|
20
|
+
xml = "<root><name>Jungle Julia</name></root>"
|
21
|
+
ApricotEatsGorilla[xml].should == { :name => "Jungle Julia" }
|
22
|
+
end
|
23
|
+
|
24
|
+
it "converts a given XML with a custom root node into a Hash" do
|
25
|
+
xml = "<root><something><name>Jungle Julia</name></something></root>"
|
26
|
+
ApricotEatsGorilla[xml, "//something"].should == { :name => "Jungle Julia" }
|
27
|
+
end
|
28
|
+
|
29
|
+
it "converts a given Hash into XML" do
|
30
|
+
hash = { "apricot" => "eats gorilla" }
|
31
|
+
ApricotEatsGorilla[hash] == "<apricot>eats gorilla</apricot>"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper")
|
2
|
+
|
3
|
+
describe ApricotEatsGorilla do
|
4
|
+
include SpecHelper
|
5
|
+
|
6
|
+
describe "hash_to_xml" do
|
7
|
+
before { reset_library_options }
|
8
|
+
|
9
|
+
it "converts Hash key Symbols into Strings" do
|
10
|
+
hash = { :apricot => { :eats => [ :gorilla, "snake" ] } }
|
11
|
+
ApricotEatsGorilla.hash_to_xml(hash).should ==
|
12
|
+
"<apricot><eats>gorilla</eats><eats>snake</eats></apricot>"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "converts lowerCamelCase Hash keys to snake_case" do
|
16
|
+
hash = { :apricot => { :eats => { :lots_of => "gorillas" } } }
|
17
|
+
ApricotEatsGorilla.hash_to_xml(hash).should ==
|
18
|
+
"<apricot><eats><lotsOf>gorillas</lotsOf></eats></apricot>"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "does not convert lowerCamelCase Hash keys to snake_case if this was disabled" do
|
22
|
+
ApricotEatsGorilla.disable_tag_names_to_lower_camel_case = true
|
23
|
+
hash = { :apricot => { :eats => { :lots_of => "gorillas" } } }
|
24
|
+
ApricotEatsGorilla.hash_to_xml(hash).should ==
|
25
|
+
"<apricot><eats><lots_of>gorillas</lots_of></eats></apricot>"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "converts values responding to to_s into Strings" do
|
29
|
+
hash = { :apricot => { :with => 100.01, :when => nil, :what => :gorillas } }
|
30
|
+
ApricotEatsGorilla.hash_to_xml(hash).should ==
|
31
|
+
"<apricot><what>gorillas</what>" <<
|
32
|
+
"<when></when><with>100.01</with></apricot>"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "converts DateTime objects into xsd:dateTime Strings" do
|
36
|
+
date = DateTime.new(y=2009, m=9, d=1, h=12, min=0, s=8)
|
37
|
+
hash = { :apricot => { :eats => { :at => date } } }
|
38
|
+
ApricotEatsGorilla.hash_to_xml(hash).should ==
|
39
|
+
"<apricot><eats><at>2009-09-01T12:00:08</at></eats></apricot>"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "converts objects responding to 'to_datetime' into xsd:dateTime Strings" do
|
43
|
+
TestObject = Struct.new(:whatever) do
|
44
|
+
def to_datetime
|
45
|
+
DateTime.new(y=2009, m=9, d=1, h=12, min=0, s=8)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
hash = { :apricot => { :eats => { :at => TestObject.new } } }
|
49
|
+
ApricotEatsGorilla.hash_to_xml(hash).should ==
|
50
|
+
"<apricot><eats><at>2009-09-01T12:00:08</at></eats></apricot>"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "applies namespaces nodes defined via nodes_to_namespace" do
|
54
|
+
ApricotEatsGorilla.nodes_to_namespace = { :wsdl => [ :apricot ] }
|
55
|
+
hash = { :apricot => { :eats => "Gorilla" } }
|
56
|
+
ApricotEatsGorilla.hash_to_xml(hash).should ==
|
57
|
+
"<wsdl:apricot><eats>Gorilla</eats></wsdl:apricot>"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "converts a Hash containing only one key and a value into one node with content" do
|
61
|
+
hash = { "apricot" => "eats Gorilla" }
|
62
|
+
ApricotEatsGorilla.hash_to_xml(hash).should == "<apricot>eats Gorilla</apricot>"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "converts a nested Hash into nested nodes" do
|
66
|
+
hash = { "apricot" => { "eats" => "gorilla", "drinks" => "beer" } }
|
67
|
+
ApricotEatsGorilla.hash_to_xml(hash).should ==
|
68
|
+
"<apricot><drinks>beer</drinks><eats>gorilla</eats></apricot>"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "converts a Hash containing an Array into multiple nodes" do
|
72
|
+
hash = { "apricot" => { "eats" => [ "gorilla", "snake" ] } }
|
73
|
+
ApricotEatsGorilla.hash_to_xml(hash).should ==
|
74
|
+
"<apricot><eats>gorilla</eats><eats>snake</eats></apricot>"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper")
|
2
|
+
|
3
|
+
describe ApricotEatsGorilla do
|
4
|
+
|
5
|
+
describe "soap_envelope" do
|
6
|
+
before { ApricotEatsGorilla.sort_keys = true }
|
7
|
+
|
8
|
+
it "returns an empty SOAP envelope with a SOAP 1.1 envelope namespace" do
|
9
|
+
ApricotEatsGorilla.soap_envelope.should ==
|
10
|
+
'<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">' <<
|
11
|
+
'<env:Header /><env:Body /></env:Envelope>'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns a SOAP envelope with a custom namespace and body content" do
|
15
|
+
ApricotEatsGorilla.soap_envelope(:wsdl => "http://example.com") do
|
16
|
+
"<id>123</id>"
|
17
|
+
end.should == '<env:Envelope' <<
|
18
|
+
' xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"' <<
|
19
|
+
' xmlns:wsdl="http://example.com">' <<
|
20
|
+
'<env:Header />' <<
|
21
|
+
'<env:Body><id>123</id></env:Body></env:Envelope>'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "does not change an already defined SOAP envelope namespace" do
|
25
|
+
ApricotEatsGorilla.soap_envelope(:env => "http://example.com").should ==
|
26
|
+
'<env:Envelope xmlns:env="http://example.com">' <<
|
27
|
+
'<env:Header />' <<
|
28
|
+
'<env:Body /></env:Envelope>'
|
29
|
+
end
|
30
|
+
|
31
|
+
it "sets the SOAP envelope namespace for SOAP version 1.2 if requested" do
|
32
|
+
ApricotEatsGorilla.soap_envelope({}, {}, 2).should ==
|
33
|
+
'<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">' <<
|
34
|
+
'<env:Header />' <<
|
35
|
+
'<env:Body /></env:Envelope>'
|
36
|
+
end
|
37
|
+
|
38
|
+
it "does not set a SOAP envelope namespace in case of an invalid SOAP version" do
|
39
|
+
ApricotEatsGorilla.soap_envelope({}, {}, 123).should ==
|
40
|
+
'<env:Envelope><env:Header /><env:Body /></env:Envelope>'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper")
|
2
|
+
|
3
|
+
describe XMLNode do
|
4
|
+
|
5
|
+
# strip_namespace!
|
6
|
+
describe "strip_namespace!" do
|
7
|
+
it "strips the namespace from the node" do
|
8
|
+
node = XMLNode.new("wsdl:apricot")
|
9
|
+
node.strip_namespace!
|
10
|
+
|
11
|
+
node.should == "apricot"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# to_snake_case!
|
16
|
+
describe "to_snake_case!" do
|
17
|
+
it "converts the node from CamelCase to snake_case" do
|
18
|
+
node = XMLNode.new("ApricotEatsGorilla")
|
19
|
+
node.to_snake_case!
|
20
|
+
|
21
|
+
node.should == "apricot_eats_gorilla"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "converts the node from lowerCamelCase to snake_case" do
|
25
|
+
node = XMLNode.new("apricotEatsGorilla")
|
26
|
+
node.to_snake_case!
|
27
|
+
|
28
|
+
node.should == "apricot_eats_gorilla"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# namespace_from_hash!
|
33
|
+
describe "namespace_from_hash!" do
|
34
|
+
it "namespaces the node if it's included in the given Hash" do
|
35
|
+
node = XMLNode.new("apricot")
|
36
|
+
node.namespace_from_hash!(:wsdl => [ :apricot ])
|
37
|
+
|
38
|
+
node.should == "apricot"
|
39
|
+
node.to_tag.should == "<wsdl:apricot />"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "does nothing if the node is not included in the given Hash" do
|
43
|
+
node = XMLNode.new("apricot")
|
44
|
+
node.namespace_from_hash!(:wsdl => [ :some_key ])
|
45
|
+
|
46
|
+
node.should == "apricot"
|
47
|
+
node.to_tag.should == "<apricot />"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# to_tag
|
52
|
+
describe "to_tag" do
|
53
|
+
it "returns an empty-element tag for a bare node" do
|
54
|
+
node = XMLNode.new("apricot")
|
55
|
+
node.to_tag.should == "<apricot />"
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns a namespaced empty-element tag for a namespaced node" do
|
59
|
+
node = XMLNode.new("apricot")
|
60
|
+
node.namespace_from_hash!(:wsdl => [ :apricot ])
|
61
|
+
|
62
|
+
node.to_tag.should == "<wsdl:apricot />"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "returns an empty-element tag with an attribute for an attributed node" do
|
66
|
+
node = XMLNode.new("apricot")
|
67
|
+
node.attributes = { :wsdl => "http://example.com" }
|
68
|
+
|
69
|
+
node.to_tag.should == '<apricot xmlns:wsdl="http://example.com" />'
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns a node with body content for a node with content" do
|
73
|
+
node = XMLNode.new("apricot")
|
74
|
+
node.body = "eats gorilla"
|
75
|
+
|
76
|
+
node.to_tag.should == "<apricot>eats gorilla</apricot>"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper")
|
2
|
+
|
3
|
+
describe ApricotEatsGorilla do
|
4
|
+
include SpecHelper
|
5
|
+
|
6
|
+
describe "xml_to_hash" do
|
7
|
+
before { reset_library_options }
|
8
|
+
|
9
|
+
it "converts Hash keys to Symbols" do
|
10
|
+
xml = "<root><name>Jungle Julia</name></root>"
|
11
|
+
ApricotEatsGorilla.xml_to_hash(xml).should == { :name => "Jungle Julia" }
|
12
|
+
end
|
13
|
+
|
14
|
+
it "does not convert Hash keys to Symbols if this was disabled" do
|
15
|
+
ApricotEatsGorilla.disable_hash_keys_to_symbols = true
|
16
|
+
xml = "<root><name>Jungle Julia</name></root>"
|
17
|
+
ApricotEatsGorilla.xml_to_hash(xml).should == { "name" => "Jungle Julia" }
|
18
|
+
end
|
19
|
+
|
20
|
+
it "converts String values of 'true' and 'false' into TrueClass and FalseClass" do
|
21
|
+
xml = "<root><yes>true</yes><no>false</no></root>"
|
22
|
+
ApricotEatsGorilla.xml_to_hash(xml).should == { :yes => true, :no => false }
|
23
|
+
end
|
24
|
+
|
25
|
+
it "converts String values matching the SOAP dateTime format to DateTime objects" do
|
26
|
+
date = "2009-08-05T11:22:08"
|
27
|
+
date_with_offset = "2009-08-05T11:22:08+02:00"
|
28
|
+
xml = "<root><date>#{date}</date><dateWithOffset>#{date_with_offset}</dateWithOffset></root>"
|
29
|
+
ApricotEatsGorilla.xml_to_hash(xml).should ==
|
30
|
+
{ :date => DateTime.parse(date), :date_with_offset => DateTime.parse(date_with_offset) }
|
31
|
+
end
|
32
|
+
|
33
|
+
it "converts empty-element tags to 'nil'" do
|
34
|
+
xml = "<contact><name>Jungle Julia</name><email /></contact>"
|
35
|
+
ApricotEatsGorilla.xml_to_hash(xml).should == { :name => "Jungle Julia", :email => nil }
|
36
|
+
end
|
37
|
+
|
38
|
+
it "converts lowerCamelCase nodes to snake_case" do
|
39
|
+
xml = "<root><firstName>Jungle</firstName><lastName>Julia</lastName></root>"
|
40
|
+
ApricotEatsGorilla.xml_to_hash(xml).should == { :first_name => "Jungle", :last_name => "Julia" }
|
41
|
+
end
|
42
|
+
|
43
|
+
it "does not convert lowerCamelCase nodes to snake_case if this was disabled" do
|
44
|
+
ApricotEatsGorilla.disable_hash_keys_to_snake_case = true
|
45
|
+
xml = "<root><firstName>Jungle</firstName><lastName>Julia</lastName></root>"
|
46
|
+
ApricotEatsGorilla.xml_to_hash(xml).should == { :firstName => "Jungle", :lastName => "Julia" }
|
47
|
+
end
|
48
|
+
|
49
|
+
it "removes namespaces from nodes" do
|
50
|
+
xml = "<root><wsdl:apricot><eats>Gorilla</eats></wsdl:apricot></root>"
|
51
|
+
ApricotEatsGorilla.xml_to_hash(xml).should == { :apricot => { :eats => "Gorilla" } }
|
52
|
+
end
|
53
|
+
|
54
|
+
it "removes attributes from nodes" do
|
55
|
+
xml = '<root><contact id="123">Jungle Julia</contact></root>'
|
56
|
+
ApricotEatsGorilla.xml_to_hash(xml).should == { :contact => "Jungle Julia" }
|
57
|
+
end
|
58
|
+
|
59
|
+
it "starts translating XML at a given custom root node" do
|
60
|
+
xml = '<root><contact><name>Jungle Julia</name></contact></root>'
|
61
|
+
ApricotEatsGorilla.xml_to_hash(xml, "//contact").should == { :name => "Jungle Julia" }
|
62
|
+
end
|
63
|
+
|
64
|
+
it "returns an Array of nodes and values in case of multiple root nodes" do
|
65
|
+
xml = '<root><return><id>1</id></return><return><id>2</id></return></root>'
|
66
|
+
ApricotEatsGorilla.xml_to_hash(xml, "//return").should == [{ :id => "1" }, { :id => "2" }]
|
67
|
+
end
|
68
|
+
|
69
|
+
it "returns the value of a node if it does not contain any subnodes" do
|
70
|
+
xml = '<root><return>123</return></root>'
|
71
|
+
ApricotEatsGorilla.xml_to_hash(xml, "//return").should == "123"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "returns an empty Hash in case the root node is an empty-element tag" do
|
75
|
+
xml = '<root><return /></root>'
|
76
|
+
ApricotEatsGorilla.xml_to_hash(xml, "//return").should == {}
|
77
|
+
end
|
78
|
+
|
79
|
+
it "returns an Array of values in case of multiple root nodes without subnodes" do
|
80
|
+
xml = '<root><return>123</return><return>456</return></root>'
|
81
|
+
ApricotEatsGorilla.xml_to_hash(xml, "//return").should == ["123", "456"]
|
82
|
+
end
|
83
|
+
|
84
|
+
it "returns a Hash containing an Array of content for multiple subnodes" do
|
85
|
+
xml = '<root><return><items>first</items><items>second</items></return></root>'
|
86
|
+
ApricotEatsGorilla.xml_to_hash(xml, "//return").should == { :items => ["first", "second"] }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
gem "rspec", ">= 1.2.8"
|
3
|
+
require "spec"
|
4
|
+
require File.join(File.dirname(__FILE__), "..", "lib", "apricoteatsgorilla")
|
5
|
+
|
6
|
+
Spec::Runner.configure do |config|
|
7
|
+
config.mock_with :rr
|
8
|
+
end
|
9
|
+
|
10
|
+
module SpecHelper
|
11
|
+
def reset_library_options
|
12
|
+
ApricotEatsGorilla.setup do |setup|
|
13
|
+
setup.sort_keys = true
|
14
|
+
setup.disable_tag_names_to_lower_camel_case = false
|
15
|
+
setup.disable_hash_keys_to_snake_case = false
|
16
|
+
setup.disable_hash_keys_to_symbols = false
|
17
|
+
setup.nodes_to_namespace = nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: apricoteatsgorilla
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Harrington
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-06 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hpricot
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - "="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.8.241
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.2.8
|
34
|
+
version:
|
35
|
+
description: SOAP communication helper
|
36
|
+
email: me@rubiii.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README.rdoc
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- README.rdoc
|
46
|
+
- Rakefile
|
47
|
+
- VERSION
|
48
|
+
- apricoteatsgorilla.gemspec
|
49
|
+
- lib/apricoteatsgorilla.rb
|
50
|
+
- lib/apricoteatsgorilla/apricoteatsgorilla.rb
|
51
|
+
- lib/apricoteatsgorilla/xml_node.rb
|
52
|
+
- spec/apricoteatsgorilla/apricoteatsgorilla_spec.rb
|
53
|
+
- spec/apricoteatsgorilla/hash_to_xml_spec.rb
|
54
|
+
- spec/apricoteatsgorilla/soap_envelope_spec.rb
|
55
|
+
- spec/apricoteatsgorilla/xml_node_spec.rb
|
56
|
+
- spec/apricoteatsgorilla/xml_to_hash_spec.rb
|
57
|
+
- spec/spec_helper.rb
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://github.com/rubiii/apricoteatsgorilla
|
60
|
+
licenses: []
|
61
|
+
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options:
|
64
|
+
- --charset=UTF-8
|
65
|
+
- --title
|
66
|
+
- Apricot eats Gorilla
|
67
|
+
- --main
|
68
|
+
- README.rdoc
|
69
|
+
- --line-numbers
|
70
|
+
- --inline-source
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.5
|
89
|
+
signing_key:
|
90
|
+
specification_version: 2
|
91
|
+
summary: SOAP communication helper
|
92
|
+
test_files:
|
93
|
+
- spec/apricoteatsgorilla/apricoteatsgorilla_spec.rb
|
94
|
+
- spec/apricoteatsgorilla/hash_to_xml_spec.rb
|
95
|
+
- spec/apricoteatsgorilla/soap_envelope_spec.rb
|
96
|
+
- spec/apricoteatsgorilla/xml_node_spec.rb
|
97
|
+
- spec/apricoteatsgorilla/xml_to_hash_spec.rb
|
98
|
+
- spec/spec_helper.rb
|