lolsoap 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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">
|