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