lolsoap 0.1.4 → 0.2.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.
- data/README.md +24 -3
- data/VERSION +1 -1
- data/lib/lolsoap/builder.rb +12 -1
- data/lib/lolsoap/envelope.rb +10 -6
- data/lib/lolsoap/fault.rb +16 -3
- data/lib/lolsoap/request.rb +15 -4
- data/lib/lolsoap/wsdl/element.rb +4 -4
- data/lib/lolsoap/wsdl/type.rb +17 -15
- data/lib/lolsoap/wsdl.rb +40 -32
- data/lib/lolsoap/wsdl_parser.rb +100 -52
- data/lolsoap.gemspec +4 -3
- data/test/fixtures/stock_quote.wsdl +8 -5
- data/test/fixtures/stock_quote_fault_soap_1_1.xml +10 -0
- data/test/integration/test_envelope.rb +4 -0
- data/test/integration/test_wsdl.rb +3 -4
- data/test/unit/test_builder.rb +1 -0
- data/test/unit/test_envelope.rb +23 -3
- data/test/unit/test_fault.rb +33 -15
- data/test/unit/test_request.rb +14 -14
- data/test/unit/test_response.rb +1 -1
- data/test/unit/test_wsdl.rb +74 -93
- data/test/unit/test_wsdl_parser.rb +46 -32
- data/test/unit/wsdl/test_type.rb +4 -4
- metadata +40 -14
data/README.md
CHANGED
@@ -36,7 +36,9 @@ client = LolSoap::Client.new(File.read('lolapi.wsdl'))
|
|
36
36
|
request = client.request('getLols')
|
37
37
|
|
38
38
|
# Populate the request with some data. Namespacing is taken care of
|
39
|
-
# using the type data from the WSDL.
|
39
|
+
# using the type data from the WSDL. The WSDL also tells us whether
|
40
|
+
# a given name (e.g. lolFactor below) should be treated as an
|
41
|
+
# attribute or a sub-element.
|
40
42
|
request.body do |b|
|
41
43
|
b.lolFactor '11'
|
42
44
|
b.lolDuration 'lolever'
|
@@ -65,10 +67,11 @@ p response.body_hash
|
|
65
67
|
|
66
68
|
## Bugs/Features ##
|
67
69
|
|
68
|
-
* SOAP 1.1 is not supported. Patches to add support will be considered
|
69
|
-
if they don't add too much extra complexity.
|
70
70
|
* WSSE is not supported.
|
71
71
|
* Assumes that you are able to supply a WSDL document for the service.
|
72
|
+
* Some of the finer details of namespace handling may be glossed over.
|
73
|
+
This is just pragmatism; patches to improve namespace handling are
|
74
|
+
welcome.
|
72
75
|
|
73
76
|
## Overview ##
|
74
77
|
|
@@ -100,6 +103,24 @@ The others:
|
|
100
103
|
|
101
104
|
Development sponsored by [Loco2](http://loco2.com/).
|
102
105
|
|
106
|
+
## Changelog ##
|
107
|
+
|
108
|
+
### 0.2 ###
|
109
|
+
|
110
|
+
* SOAP 1.1 support
|
111
|
+
* Better handling of namespaces in the XML schema. You should now be
|
112
|
+
able to have two types a:foo and b:foo and it will Just Work. This
|
113
|
+
introduces some API incompatibilities with version 1.1. Specifically,
|
114
|
+
`LolSoap::WSDL#types` is now keyed based on a prefixed type name
|
115
|
+
rather than an unprefixed type name. This shouldn't affect you if
|
116
|
+
you're not using `LolSoap::WSDL#types` directly.
|
117
|
+
* Add support for building attributes with `LolSoap::Builder` based on
|
118
|
+
the XML Schema information.
|
119
|
+
|
120
|
+
### 0.1 ###
|
121
|
+
|
122
|
+
Initial release
|
123
|
+
|
103
124
|
## License ##
|
104
125
|
|
105
126
|
(The MIT License)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/lolsoap/builder.rb
CHANGED
@@ -55,6 +55,10 @@ module LolSoap
|
|
55
55
|
__prefixed_tag__(@type.prefix, @type.sub_type(name.to_s), name, *args, &block)
|
56
56
|
end
|
57
57
|
|
58
|
+
def __attribute__(name, value)
|
59
|
+
@node[name.to_s] = value.to_s
|
60
|
+
end
|
61
|
+
|
58
62
|
# @private
|
59
63
|
def __prefixed_tag__(prefix, sub_type, name, *args)
|
60
64
|
sub_node = @node.document.create_element(name.to_s, *args)
|
@@ -88,6 +92,13 @@ module LolSoap
|
|
88
92
|
|
89
93
|
private
|
90
94
|
|
91
|
-
alias method_missing __tag__
|
95
|
+
# alias method_missing __tag__
|
96
|
+
def method_missing(name, *args, &block)
|
97
|
+
if @type.has_attribute?(name.to_s)
|
98
|
+
__attribute__(name, *args)
|
99
|
+
else
|
100
|
+
__tag__(name, *args, &block)
|
101
|
+
end
|
102
|
+
end
|
92
103
|
end
|
93
104
|
end
|
data/lib/lolsoap/envelope.rb
CHANGED
@@ -6,10 +6,10 @@ module LolSoap
|
|
6
6
|
attr_reader :wsdl, :operation, :doc
|
7
7
|
|
8
8
|
# @private
|
9
|
-
|
9
|
+
SOAP_1_1 = 'http://schemas.xmlsoap.org/soap/envelope/'
|
10
10
|
|
11
11
|
# @private
|
12
|
-
|
12
|
+
SOAP_1_2 = 'http://www.w3.org/2003/05/soap-envelope'
|
13
13
|
|
14
14
|
def initialize(wsdl, operation, doc = Nokogiri::XML::Document.new)
|
15
15
|
@wsdl = wsdl
|
@@ -54,16 +54,20 @@ module LolSoap
|
|
54
54
|
operation.output
|
55
55
|
end
|
56
56
|
|
57
|
-
def to_xml
|
58
|
-
doc.to_xml
|
57
|
+
def to_xml(options = {})
|
58
|
+
doc.to_xml(options)
|
59
59
|
end
|
60
60
|
|
61
61
|
def soap_prefix
|
62
|
-
|
62
|
+
'soap'
|
63
63
|
end
|
64
64
|
|
65
65
|
def soap_namespace
|
66
|
-
|
66
|
+
soap_version == '1.2' ? SOAP_1_2 : SOAP_1_1
|
67
|
+
end
|
68
|
+
|
69
|
+
def soap_version
|
70
|
+
wsdl.soap_version
|
67
71
|
end
|
68
72
|
|
69
73
|
private
|
data/lib/lolsoap/fault.rb
CHANGED
@@ -11,16 +11,29 @@ module LolSoap
|
|
11
11
|
request.soap_namespace
|
12
12
|
end
|
13
13
|
|
14
|
+
def soap_version
|
15
|
+
request.soap_version
|
16
|
+
end
|
17
|
+
|
14
18
|
def code
|
15
|
-
node.at_xpath(
|
19
|
+
node.at_xpath(
|
20
|
+
soap_version == '1.2' ? './soap:Code/soap:Value' : './soap:faultcode',
|
21
|
+
'soap' => soap_namespace
|
22
|
+
).text.to_s
|
16
23
|
end
|
17
24
|
|
18
25
|
def reason
|
19
|
-
node.at_xpath(
|
26
|
+
node.at_xpath(
|
27
|
+
soap_version == '1.2' ? './soap:Reason/soap:Text' : './soap:faultstring',
|
28
|
+
'soap' => soap_namespace
|
29
|
+
).text.to_s
|
20
30
|
end
|
21
31
|
|
22
32
|
def detail
|
23
|
-
node.at_xpath(
|
33
|
+
node.at_xpath(
|
34
|
+
soap_version == '1.2' ? './soap:Detail/*' : './soap:detail/*',
|
35
|
+
'soap' => soap_namespace
|
36
|
+
).to_xml
|
24
37
|
end
|
25
38
|
end
|
26
39
|
end
|
data/lib/lolsoap/request.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
module LolSoap
|
2
2
|
# Represents a HTTP request containing a SOAP Envelope
|
3
3
|
class Request
|
4
|
-
attr_reader
|
4
|
+
attr_reader :envelope
|
5
|
+
attr_accessor :xml_options
|
5
6
|
|
6
7
|
def initialize(envelope)
|
7
|
-
@envelope
|
8
|
+
@envelope = envelope
|
9
|
+
@xml_options = {}
|
8
10
|
end
|
9
11
|
|
10
12
|
# @see Envelope#body
|
@@ -22,6 +24,11 @@ module LolSoap
|
|
22
24
|
envelope.soap_namespace
|
23
25
|
end
|
24
26
|
|
27
|
+
# The SOAP version in use
|
28
|
+
def soap_version
|
29
|
+
envelope.soap_version
|
30
|
+
end
|
31
|
+
|
25
32
|
# URL to be POSTed to
|
26
33
|
def url
|
27
34
|
envelope.endpoint
|
@@ -40,7 +47,11 @@ module LolSoap
|
|
40
47
|
# The MIME type of the request. This is always application/soap+xml,
|
41
48
|
# but it could be overridden in a subclass.
|
42
49
|
def mime
|
43
|
-
'
|
50
|
+
if soap_version == '1.1'
|
51
|
+
'text/xml'
|
52
|
+
else
|
53
|
+
'application/soap+xml'
|
54
|
+
end
|
44
55
|
end
|
45
56
|
|
46
57
|
# The charset of the request. This is always UTF-8, but it could be
|
@@ -66,7 +77,7 @@ module LolSoap
|
|
66
77
|
|
67
78
|
# The content to be sent in the HTTP request
|
68
79
|
def content
|
69
|
-
@content ||= envelope.to_xml
|
80
|
+
@content ||= envelope.to_xml(xml_options)
|
70
81
|
end
|
71
82
|
end
|
72
83
|
end
|
data/lib/lolsoap/wsdl/element.rb
CHANGED
@@ -9,14 +9,14 @@ class LolSoap::WSDL
|
|
9
9
|
@singular = singular
|
10
10
|
end
|
11
11
|
|
12
|
-
def type
|
13
|
-
@type ||= wsdl.type(@type_name.split(':').last)
|
14
|
-
end
|
15
|
-
|
16
12
|
def singular?
|
17
13
|
@singular == true
|
18
14
|
end
|
19
15
|
|
16
|
+
def type
|
17
|
+
@type ||= wsdl.type(@type_name)
|
18
|
+
end
|
19
|
+
|
20
20
|
def inspect
|
21
21
|
"<#{self.class} name=#{name.inspect} type=#{@type_name.inspect}>"
|
22
22
|
end
|
data/lib/lolsoap/wsdl/type.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
class LolSoap::WSDL
|
2
4
|
class Type
|
3
|
-
attr_reader :name, :
|
5
|
+
attr_reader :name, :prefix
|
4
6
|
|
5
|
-
def initialize(
|
6
|
-
@
|
7
|
-
@
|
8
|
-
@
|
9
|
-
@
|
7
|
+
def initialize(name, prefix, elements, attributes)
|
8
|
+
@name = name
|
9
|
+
@prefix = prefix
|
10
|
+
@elements = elements
|
11
|
+
@attributes = Set.new(attributes)
|
10
12
|
end
|
11
13
|
|
12
14
|
def elements
|
@@ -21,18 +23,18 @@ class LolSoap::WSDL
|
|
21
23
|
element(name).type
|
22
24
|
end
|
23
25
|
|
24
|
-
def
|
25
|
-
|
26
|
+
def attributes
|
27
|
+
@attributes.to_a
|
26
28
|
end
|
27
29
|
|
28
|
-
def
|
29
|
-
|
30
|
-
"name=#{(prefix + ':' + name).inspect} " \
|
31
|
-
"elements=#{elements.inspect}>"
|
30
|
+
def has_attribute?(name)
|
31
|
+
@attributes.include?(name)
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
def inspect
|
35
|
+
"<#{self.class} name=\"#{prefix}:#{name}\" " \
|
36
|
+
"elements=#{elements.inspect} " \
|
37
|
+
"attributes=#{attributes.inspect}>"
|
38
|
+
end
|
37
39
|
end
|
38
40
|
end
|
data/lib/lolsoap/wsdl.rb
CHANGED
@@ -13,75 +13,83 @@ module LolSoap
|
|
13
13
|
new(WSDLParser.parse(raw))
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
# The SOAP endpoint URL
|
17
|
+
attr_reader :endpoint
|
18
|
+
|
19
|
+
# Hash of namespaces used in the WSDL document (keys are prefixes)
|
20
|
+
attr_reader :namespaces
|
21
|
+
|
22
|
+
# Hash of namespace prefixes used in the WSDL document (keys are namespace URIs)
|
23
|
+
attr_reader :prefixes
|
24
|
+
|
25
|
+
# The version of SOAP detected.
|
26
|
+
attr_reader :soap_version
|
17
27
|
|
18
28
|
def initialize(parser)
|
19
|
-
@
|
29
|
+
@types = load_types(parser)
|
30
|
+
@operations = load_operations(parser)
|
31
|
+
@endpoint = parser.endpoint
|
32
|
+
@namespaces = parser.namespaces
|
33
|
+
@prefixes = parser.prefixes
|
34
|
+
@soap_version = parser.soap_version
|
20
35
|
end
|
21
36
|
|
22
37
|
# Hash of operations that are supports by the SOAP service
|
23
38
|
def operations
|
24
|
-
|
39
|
+
@operations.dup
|
25
40
|
end
|
26
41
|
|
27
42
|
# Get a single operation
|
28
43
|
def operation(name)
|
29
|
-
|
44
|
+
@operations.fetch(name)
|
30
45
|
end
|
31
46
|
|
32
47
|
# Hash of types declared by the service
|
33
48
|
def types
|
34
|
-
|
49
|
+
@types.dup
|
35
50
|
end
|
36
51
|
|
37
52
|
# Get a single type, or a NullType if the type doesn't exist
|
38
53
|
def type(name)
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
# The SOAP endpoint URL
|
43
|
-
def endpoint
|
44
|
-
parser.endpoint
|
45
|
-
end
|
46
|
-
|
47
|
-
# Hash of namespaces used in the WSDL document (keys are prefixes)
|
48
|
-
def namespaces
|
49
|
-
parser.namespaces
|
50
|
-
end
|
51
|
-
|
52
|
-
# Hash of namespace prefixes used in the WSDL document (keys are namespace URIs)
|
53
|
-
def prefixes
|
54
|
-
namespaces.invert
|
54
|
+
@types.fetch(name) { NullType.new }
|
55
55
|
end
|
56
56
|
|
57
57
|
# Namespaces used by the types (a subset of #namespaces)
|
58
58
|
def type_namespaces
|
59
|
-
Hash[
|
59
|
+
Hash[@types.values.map { |type| [type.prefix, namespaces[type.prefix]] }]
|
60
60
|
end
|
61
61
|
|
62
62
|
def inspect
|
63
63
|
"<#{self.class} " \
|
64
|
-
"namespaces=#{namespaces.inspect} " \
|
65
|
-
"operations=#{operations.keys.inspect} " \
|
66
|
-
"types=#{types.keys.inspect}>"
|
64
|
+
"namespaces=#{@namespaces.inspect} " \
|
65
|
+
"operations=#{@operations.keys.inspect} " \
|
66
|
+
"types=#{@types.keys.inspect}>"
|
67
67
|
end
|
68
68
|
|
69
69
|
private
|
70
70
|
|
71
71
|
# @private
|
72
|
-
def load_operations
|
73
|
-
|
72
|
+
def load_operations(parser)
|
73
|
+
Hash[
|
74
74
|
parser.operations.map do |k, op|
|
75
|
-
[k, Operation.new(self, op[:action], type(op[:input]
|
75
|
+
[k, Operation.new(self, op[:action], type(op[:input]), type(op[:output]))]
|
76
76
|
end
|
77
77
|
]
|
78
78
|
end
|
79
79
|
|
80
80
|
# @private
|
81
|
-
def load_types
|
82
|
-
|
83
|
-
parser.types.map do |
|
84
|
-
[
|
81
|
+
def load_types(parser)
|
82
|
+
Hash[
|
83
|
+
parser.types.map do |prefixed_name, type|
|
84
|
+
[
|
85
|
+
prefixed_name,
|
86
|
+
Type.new(
|
87
|
+
type[:name],
|
88
|
+
type[:prefix],
|
89
|
+
build_elements(type[:elements]),
|
90
|
+
type[:attributes]
|
91
|
+
)
|
92
|
+
]
|
85
93
|
end
|
86
94
|
]
|
87
95
|
end
|
data/lib/lolsoap/wsdl_parser.rb
CHANGED
@@ -3,11 +3,47 @@ require 'nokogiri'
|
|
3
3
|
module LolSoap
|
4
4
|
# @private
|
5
5
|
class WSDLParser
|
6
|
-
|
7
|
-
:
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
class Type
|
7
|
+
attr_reader :parser, :node, :target_namespace, :name, :prefix
|
8
|
+
|
9
|
+
def initialize(parser, node, target_namespace)
|
10
|
+
@parser = parser
|
11
|
+
@node = node
|
12
|
+
@target_namespace = target_namespace
|
13
|
+
@prefix, @name = prefix_and_name(node.attr('name'))
|
14
|
+
end
|
15
|
+
|
16
|
+
def name_with_prefix
|
17
|
+
"#{prefix}:#{name}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def elements
|
21
|
+
Hash[
|
22
|
+
node.xpath('.//xs:element', parser.ns).map do |element|
|
23
|
+
max_occurs = element.attribute('maxOccurs').to_s
|
24
|
+
|
25
|
+
[
|
26
|
+
prefix_and_name(element.attr('name')).last,
|
27
|
+
{
|
28
|
+
:type => prefix_and_name(element.attr('type')).join(':'),
|
29
|
+
:singular => max_occurs.empty? || max_occurs == '1'
|
30
|
+
}
|
31
|
+
]
|
32
|
+
end
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
def attributes
|
37
|
+
node.xpath('.//xs:attribute/@name', parser.ns).map(&:text)
|
38
|
+
end
|
39
|
+
|
40
|
+
def prefix_and_name(string)
|
41
|
+
parser.prefix_and_name(string, target_namespace)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
SOAP_1_1 = 'http://schemas.xmlsoap.org/wsdl/soap/'
|
46
|
+
SOAP_1_2 = 'http://schemas.xmlsoap.org/wsdl/soap12/'
|
11
47
|
|
12
48
|
attr_reader :doc
|
13
49
|
|
@@ -27,79 +63,76 @@ module LolSoap
|
|
27
63
|
end
|
28
64
|
end
|
29
65
|
|
66
|
+
# We invert the hash in a deterministic way so that the results are repeatable.
|
67
|
+
def prefixes
|
68
|
+
@prefixes ||= Hash[namespaces.sort_by { |k, v| k }.uniq { |k, v| v }].invert
|
69
|
+
end
|
70
|
+
|
30
71
|
def endpoint
|
31
|
-
@endpoint ||= doc.at_xpath(
|
32
|
-
|
33
|
-
|
34
|
-
|
72
|
+
@endpoint ||= doc.at_xpath('/d:definitions/d:service/d:port/s:address/@location', ns).to_s
|
73
|
+
end
|
74
|
+
|
75
|
+
def schemas
|
76
|
+
doc.xpath('/d:definitions/d:types/xs:schema', ns)
|
35
77
|
end
|
36
78
|
|
37
79
|
def types
|
38
80
|
@types ||= begin
|
39
|
-
types =
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
{
|
53
|
-
:name => name,
|
54
|
-
:namespace => namespace,
|
55
|
-
:elements => Hash[elements.map { |e| [e.attribute('name').to_s, element_hash(e)] }]
|
56
|
-
}
|
57
|
-
]
|
81
|
+
types = {}
|
82
|
+
schemas.each do |schema|
|
83
|
+
target_namespace = schema.attr('targetNamespace').to_s
|
84
|
+
|
85
|
+
schema.xpath('xs:element[@name] | xs:complexType[@name]', ns).each do |node|
|
86
|
+
type = Type.new(self, node, target_namespace)
|
87
|
+
|
88
|
+
types[type.name_with_prefix] = {
|
89
|
+
:name => type.name,
|
90
|
+
:prefix => type.prefix,
|
91
|
+
:elements => type.elements,
|
92
|
+
:attributes => type.attributes
|
93
|
+
}
|
58
94
|
end
|
59
|
-
|
95
|
+
end
|
96
|
+
types
|
60
97
|
end
|
61
98
|
end
|
62
99
|
|
63
100
|
def messages
|
64
101
|
@messages ||= Hash[
|
65
|
-
doc.xpath('/d:definitions/d:message',
|
66
|
-
element = msg.at_xpath('./d:part/@element',
|
67
|
-
[msg.attribute('name').to_s,
|
102
|
+
doc.xpath('/d:definitions/d:message', ns).map do |msg|
|
103
|
+
element = msg.at_xpath('./d:part/@element', ns).to_s
|
104
|
+
[msg.attribute('name').to_s, prefix_and_name(element).join(':')]
|
68
105
|
end
|
69
106
|
]
|
70
107
|
end
|
71
108
|
|
72
109
|
def port_type_operations
|
73
110
|
@port_type_operations ||= Hash[
|
74
|
-
doc.xpath('/d:definitions/d:portType/d:operation',
|
75
|
-
input = op.at_xpath('./d:input/@message',
|
76
|
-
output = op.at_xpath('./d:output/@message',
|
111
|
+
doc.xpath('/d:definitions/d:portType/d:operation', ns).map do |op|
|
112
|
+
input = op.at_xpath('./d:input/@message', ns).to_s.split(':').last
|
113
|
+
output = op.at_xpath('./d:output/@message', ns).to_s.split(':').last
|
77
114
|
name = op.attribute('name').to_s
|
78
115
|
|
79
|
-
[name, { :
|
116
|
+
[name, { :input => messages.fetch(input), :output => messages.fetch(output) }]
|
80
117
|
end
|
81
118
|
]
|
82
119
|
end
|
83
120
|
|
84
121
|
def operations
|
85
122
|
@operations ||= begin
|
86
|
-
binding = doc.at_xpath(
|
87
|
-
'/d:definitions/d:service/d:port/soap:address/../@binding',
|
88
|
-
'd' => NS[:wsdl], 'soap' => NS[:soap]
|
89
|
-
).to_s.split(':').last
|
123
|
+
binding = doc.at_xpath('/d:definitions/d:service/d:port/s:address/../@binding', ns).to_s.split(':').last
|
90
124
|
|
91
125
|
Hash[
|
92
|
-
doc.xpath("/d:definitions/d:binding[@name='#{binding}']/d:operation",
|
126
|
+
doc.xpath("/d:definitions/d:binding[@name='#{binding}']/d:operation", ns).map do |op|
|
93
127
|
name = op.attribute('name').to_s
|
94
|
-
action = op.at_xpath('./
|
128
|
+
action = op.at_xpath('./s:operation/@soapAction', ns).to_s
|
95
129
|
|
96
130
|
[
|
97
131
|
name,
|
98
132
|
{
|
99
|
-
:name => name,
|
100
133
|
:action => action,
|
101
|
-
:input => port_type_operations
|
102
|
-
:output => port_type_operations
|
134
|
+
:input => port_type_operations.fetch(name)[:input],
|
135
|
+
:output => port_type_operations.fetch(name)[:output]
|
103
136
|
}
|
104
137
|
]
|
105
138
|
end
|
@@ -107,15 +140,30 @@ module LolSoap
|
|
107
140
|
end
|
108
141
|
end
|
109
142
|
|
110
|
-
|
143
|
+
def soap_version
|
144
|
+
@soap_version ||= namespaces.values.include?(SOAP_1_2) ? '1.2' : '1.1'
|
145
|
+
end
|
111
146
|
|
112
|
-
def
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
:singular => max_occurs.empty? || max_occurs == '1'
|
147
|
+
def ns
|
148
|
+
@ns ||= {
|
149
|
+
'd' => 'http://schemas.xmlsoap.org/wsdl/',
|
150
|
+
'xs' => 'http://www.w3.org/2001/XMLSchema',
|
151
|
+
's' => soap_version == '1.2' ? SOAP_1_2 : SOAP_1_1
|
118
152
|
}
|
119
153
|
end
|
154
|
+
|
155
|
+
def prefix_and_name(prefixed_name, default_namespace = nil)
|
156
|
+
prefix, name = prefixed_name.to_s.split(':')
|
157
|
+
|
158
|
+
if name
|
159
|
+
# Ensure we always use the same prefix for a given namespace
|
160
|
+
prefix = prefixes.fetch(namespaces.fetch(prefix))
|
161
|
+
else
|
162
|
+
name = prefix
|
163
|
+
prefix = prefixes.fetch(default_namespace)
|
164
|
+
end
|
165
|
+
|
166
|
+
[prefix, name]
|
167
|
+
end
|
120
168
|
end
|
121
169
|
end
|
data/lolsoap.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "lolsoap"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jon Leighton"]
|
12
|
-
s.date = "
|
12
|
+
s.date = "2013-05-15"
|
13
13
|
s.description = "A library for dealing with SOAP requests and responses. We tear our hair out so you don't have to."
|
14
14
|
s.email = "j@jonathanleighton.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -45,6 +45,7 @@ Gem::Specification.new do |s|
|
|
45
45
|
"lolsoap.gemspec",
|
46
46
|
"test/fixtures/stock_quote.wsdl",
|
47
47
|
"test/fixtures/stock_quote_fault.xml",
|
48
|
+
"test/fixtures/stock_quote_fault_soap_1_1.xml",
|
48
49
|
"test/fixtures/stock_quote_response.xml",
|
49
50
|
"test/helper.rb",
|
50
51
|
"test/integration/test_client.rb",
|
@@ -67,7 +68,7 @@ Gem::Specification.new do |s|
|
|
67
68
|
s.homepage = "http://github.com/loco2/lolsoap"
|
68
69
|
s.licenses = ["MIT"]
|
69
70
|
s.require_paths = ["lib"]
|
70
|
-
s.rubygems_version = "1.8.
|
71
|
+
s.rubygems_version = "1.8.24"
|
71
72
|
s.summary = "A library for dealing with SOAP requests and responses."
|
72
73
|
|
73
74
|
if s.respond_to? :specification_version then
|
@@ -6,22 +6,25 @@
|
|
6
6
|
xmlns:xsd1="http://example.com/stockquote.xsd"
|
7
7
|
xmlns:xsd2="http://example.com/stockquote2.xsd"
|
8
8
|
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/"
|
9
|
+
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
9
10
|
xmlns="http://schemas.xmlsoap.org/wsdl/">
|
10
11
|
|
11
12
|
<types>
|
12
13
|
<schema targetNamespace="http://example.com/stockquote.xsd"
|
14
|
+
xmlns:xsd3="http://example.com/stockquote.xsd"
|
13
15
|
xmlns="http://www.w3.org/2001/XMLSchema">
|
14
16
|
<element name="TradePrice">
|
15
17
|
<complexType>
|
16
18
|
<all>
|
17
|
-
<element name="price" type="float"/>
|
19
|
+
<element name="xsd3:price" type="xs:float"/>
|
18
20
|
</all>
|
19
21
|
</complexType>
|
20
22
|
</element>
|
21
|
-
<complexType name="TradePriceRequest">
|
23
|
+
<complexType name="xsd3:TradePriceRequest">
|
22
24
|
<sequence>
|
23
|
-
<element name="tickerSymbol" type="string" maxOccurs="5"/>
|
25
|
+
<element name="tickerSymbol" type="xs:string" maxOccurs="5"/>
|
24
26
|
<element name="specialTickerSymbol" type="xsd2:TickerSymbol" maxOccurs="unbounded"/>
|
27
|
+
<attribute name="id" type="xs:string"/>
|
25
28
|
</sequence>
|
26
29
|
</complexType>
|
27
30
|
</schema>
|
@@ -30,7 +33,7 @@
|
|
30
33
|
xmlns="http://www.w3.org/2001/XMLSchema">
|
31
34
|
<complexType name="TickerSymbol">
|
32
35
|
<sequence>
|
33
|
-
<element name="name" type="string" maxOccurs="1"/>
|
36
|
+
<element name="name" type="xs:string" maxOccurs="1"/>
|
34
37
|
</sequence>
|
35
38
|
</complexType>
|
36
39
|
</schema>
|
@@ -41,7 +44,7 @@
|
|
41
44
|
</message>
|
42
45
|
|
43
46
|
<message name="GetLastTradePriceOutput">
|
44
|
-
<part name="body" element="
|
47
|
+
<part name="body" element="xsd3:TradePrice"/>
|
45
48
|
</message>
|
46
49
|
|
47
50
|
<portType name="StockQuotePortType">
|