cherby 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/cherby.gemspec +1 -2
- data/lib/cherby/business_object.rb +46 -10
- data/lib/cherby/cherwell.rb +35 -8
- data/lib/cherby/exceptions.rb +10 -1
- data/lib/cherby/incident.rb +1 -0
- data/spec/business_object_spec.rb +68 -2
- data/spec/cherwell_spec.rb +30 -9
- data/spec/data/empty.xml +1 -0
- data/spec/spec_helper.rb +15 -12
- metadata +3 -20
- data/spec/xml/method_response_result.mustache +0 -4
- data/spec/xml/soap_envelope.mustache +0 -6
data/cherby.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "cherby"
|
3
|
-
s.version = "0.0.
|
3
|
+
s.version = "0.0.3"
|
4
4
|
s.summary = "Cherwell-Ruby bridge"
|
5
5
|
s.description = <<-EOS
|
6
6
|
Cherby is a Ruby wrapper for the Cherwell Web Service.
|
@@ -14,7 +14,6 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.add_dependency 'savon', '>= 2.3.0'
|
15
15
|
s.add_dependency 'yajl-ruby'
|
16
16
|
s.add_dependency 'nokogiri'
|
17
|
-
s.add_dependency 'mustache'
|
18
17
|
|
19
18
|
s.add_development_dependency "rake"
|
20
19
|
s.add_development_dependency "simplecov"
|
@@ -34,9 +34,27 @@ module Cherby
|
|
34
34
|
|
35
35
|
attr_reader :dom
|
36
36
|
|
37
|
-
# Create a new instance
|
37
|
+
# Create a new BusinessObject instance from the given XML string.
|
38
38
|
def initialize(xml)
|
39
39
|
@dom = Nokogiri::XML(xml)
|
40
|
+
check_dom_format!
|
41
|
+
end
|
42
|
+
|
43
|
+
# Ensure the @dom is in the expected format for BusinessObjects.
|
44
|
+
#
|
45
|
+
# @raise [Cherby::BadFormat]
|
46
|
+
# If the DOM's structure is incorrect
|
47
|
+
#
|
48
|
+
def check_dom_format!
|
49
|
+
# Ensure XML is in expected format for BusinessObjects
|
50
|
+
if @dom.css('BusinessObject').empty?
|
51
|
+
raise Cherby::BadFormat.new(
|
52
|
+
"BusinessObject XML is missing 'BusinessObject' element")
|
53
|
+
elsif @dom.css('BusinessObject > FieldList').empty?
|
54
|
+
raise Cherby::BadFormat.new(
|
55
|
+
"BusinessObject XML is missing 'BusinessObject > FieldList' element")
|
56
|
+
end
|
57
|
+
return true
|
40
58
|
end
|
41
59
|
|
42
60
|
# Return the XML representation of this BusinessObject
|
@@ -45,9 +63,30 @@ module Cherby
|
|
45
63
|
end
|
46
64
|
|
47
65
|
# Return the node of the field with the given name.
|
66
|
+
#
|
67
|
+
# @param [String] field_name
|
68
|
+
# The `Name` attribute of the `Field` element to get.
|
69
|
+
#
|
70
|
+
# @return [Nokogiri::XML::Node, nil]
|
71
|
+
# The node for the `Field` element, or `nil` if no Field
|
72
|
+
# with the given `Name` exists.
|
73
|
+
#
|
48
74
|
def get_field_node(field_name)
|
75
|
+
check_dom_format!
|
49
76
|
selector = "BusinessObject > FieldList > Field[@Name=#{field_name}]"
|
50
|
-
|
77
|
+
return @dom.css(selector).first
|
78
|
+
end
|
79
|
+
|
80
|
+
# Get a `Field` node with the given name, or create one if it doesn't exist.
|
81
|
+
#
|
82
|
+
# @param [String] field_name
|
83
|
+
# The `Name` attribute of the `Field` element to get or create.
|
84
|
+
#
|
85
|
+
# @return [Nokogiri::XML::Node]
|
86
|
+
# The node for the existing or new `Field` element.
|
87
|
+
#
|
88
|
+
def get_or_create_field_node(field_name)
|
89
|
+
element = get_field_node(field_name)
|
51
90
|
if element.nil?
|
52
91
|
element = Nokogiri::XML::Node.new('Field', @dom)
|
53
92
|
element['Name'] = field_name
|
@@ -126,19 +165,16 @@ module Cherby
|
|
126
165
|
end
|
127
166
|
|
128
167
|
# Return the content in the field with the given name.
|
129
|
-
# TODO: Exception for unknown field name
|
130
168
|
def [](field_name)
|
131
|
-
|
132
|
-
|
133
|
-
|
169
|
+
field = get_field_node(field_name)
|
170
|
+
return field.content if field
|
171
|
+
return nil
|
134
172
|
end
|
135
173
|
|
136
174
|
# Modify the content in the field with the given name.
|
137
|
-
# TODO: Exception for unknown field name
|
138
175
|
def []=(field_name, value)
|
139
|
-
|
140
|
-
|
141
|
-
end
|
176
|
+
field = get_or_create_field_node(field_name)
|
177
|
+
field.content = value.to_s
|
142
178
|
end
|
143
179
|
|
144
180
|
# Copy designated fields from one BusinessObject to another.
|
data/lib/cherby/cherwell.rb
CHANGED
@@ -41,7 +41,7 @@ module Cherby
|
|
41
41
|
# @return [Boolean]
|
42
42
|
# `true` if login was successful
|
43
43
|
#
|
44
|
-
# @raise [LoginFailed]
|
44
|
+
# @raise [Cherby::LoginFailed]
|
45
45
|
# If login failed for any reason
|
46
46
|
#
|
47
47
|
def login(username=nil, password=nil)
|
@@ -53,7 +53,7 @@ module Cherby
|
|
53
53
|
response = @client.call(:login, :message => creds)
|
54
54
|
rescue => e
|
55
55
|
# This can happen if a bad URL is given
|
56
|
-
raise LoginFailed, e.message
|
56
|
+
raise Cherby::LoginFailed, e.message
|
57
57
|
else
|
58
58
|
if response.body[:login_response][:login_result] == true
|
59
59
|
# FIXME: Using the workaround described in this issue:
|
@@ -66,7 +66,7 @@ module Cherby
|
|
66
66
|
return true
|
67
67
|
# This can happen if invalid credentials are given
|
68
68
|
else
|
69
|
-
raise LoginFailed, "Cherwell returned false status"
|
69
|
+
raise Cherby::LoginFailed, "Cherwell returned false status"
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -85,9 +85,18 @@ module Cherby
|
|
85
85
|
#
|
86
86
|
# @return [Incident]
|
87
87
|
#
|
88
|
+
# @raise [Cherby::NotFound]
|
89
|
+
# If an error occurs when fetching the incident.
|
90
|
+
# The `message` attribute includes the error from Cherwell.
|
91
|
+
#
|
88
92
|
def incident(id)
|
89
93
|
incident_xml = get_object_xml('Incident', id)
|
90
|
-
|
94
|
+
error = self.last_error
|
95
|
+
if error
|
96
|
+
raise Cherby::NotFound.new("Cannot find Incident '#{id}': #{error}")
|
97
|
+
else
|
98
|
+
return Incident.new(incident_xml.to_s)
|
99
|
+
end
|
91
100
|
end
|
92
101
|
|
93
102
|
# Get the Cherwell task with the given public ID, and return a Task
|
@@ -95,9 +104,18 @@ module Cherby
|
|
95
104
|
#
|
96
105
|
# @return [Task]
|
97
106
|
#
|
107
|
+
# @raise [Cherby::NotFound]
|
108
|
+
# If an error occurs when fetching the task.
|
109
|
+
# The `message` attribute includes the error from Cherwell.
|
110
|
+
#
|
98
111
|
def task(id)
|
99
112
|
task_xml = get_object_xml('Task', id)
|
100
|
-
|
113
|
+
error = self.last_error
|
114
|
+
if error
|
115
|
+
raise Cherby::NotFound.new("Cannot find Task '#{id}': #{error}")
|
116
|
+
else
|
117
|
+
return Task.new(task_xml.to_s)
|
118
|
+
end
|
101
119
|
end
|
102
120
|
|
103
121
|
# Get a business object based on its public ID or RecID, and return the
|
@@ -127,6 +145,9 @@ module Cherby
|
|
127
145
|
# @return [String]
|
128
146
|
# Raw XML response string.
|
129
147
|
#
|
148
|
+
# @raise [Cherby::SoapError]
|
149
|
+
# If a Savon::SOAPFault occurs when making the request.
|
150
|
+
#
|
130
151
|
def get_object_xml(object_type, id)
|
131
152
|
# Assemble the SOAP body
|
132
153
|
body = {:busObNameOrId => object_type}
|
@@ -143,13 +164,19 @@ module Cherby
|
|
143
164
|
|
144
165
|
begin
|
145
166
|
result = @client.call_wrap(method, body)
|
146
|
-
rescue Savon::
|
147
|
-
raise SoapError
|
167
|
+
rescue Savon::SOAPFault => e
|
168
|
+
raise Cherby::SoapError.new(
|
169
|
+
"SOAPFault from method '#{method}'", e.http)
|
148
170
|
else
|
149
|
-
return result
|
171
|
+
return result.to_s
|
150
172
|
end
|
151
173
|
end
|
152
174
|
|
175
|
+
# Get a BusinessObject instance
|
176
|
+
def get_business_object(object_type, id)
|
177
|
+
xml = self.get_object_xml(object_type, id)
|
178
|
+
return BusinessObject.new(xml)
|
179
|
+
end
|
153
180
|
|
154
181
|
# Update a given Cherwell object by submitting its XML to the SOAP
|
155
182
|
# interface.
|
data/lib/cherby/exceptions.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
module Cherby
|
2
2
|
class CherbyError < RuntimeError; end
|
3
3
|
class LoginFailed < CherbyError; end
|
4
|
-
class
|
4
|
+
class NotFound < CherbyError; end
|
5
|
+
class BadFormat < CherbyError; end
|
6
|
+
|
7
|
+
class SoapError < CherbyError
|
8
|
+
attr_reader :http
|
9
|
+
def initialize(message, http=nil)
|
10
|
+
super(message)
|
11
|
+
@http = http
|
12
|
+
end
|
13
|
+
end
|
5
14
|
end # module Cherby
|
6
15
|
|
data/lib/cherby/incident.rb
CHANGED
@@ -75,14 +75,44 @@ describe Cherby::BusinessObject do
|
|
75
75
|
last_name.content.should == "Idle"
|
76
76
|
end
|
77
77
|
|
78
|
+
it "raises BadFormat if XML is missing FieldList" do
|
79
|
+
xml = %Q{
|
80
|
+
<BusinessObject Name="MySubclass">
|
81
|
+
<Whatever/>
|
82
|
+
</BusinessObject>
|
83
|
+
}
|
84
|
+
lambda do
|
85
|
+
@obj = MySubclass.new(xml)
|
86
|
+
end.should raise_error(
|
87
|
+
Cherby::BadFormat, /missing 'BusinessObject > FieldList'/)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "raises BadFormat if XML is missing BusinessObject" do
|
91
|
+
xml = %Q{
|
92
|
+
<Whatever Name="MySubclass"/>
|
93
|
+
}
|
94
|
+
lambda do
|
95
|
+
@obj = MySubclass.new(xml)
|
96
|
+
end.should raise_error(
|
97
|
+
Cherby::BadFormat, /missing 'BusinessObject'/)
|
98
|
+
end
|
78
99
|
end #initialize
|
79
100
|
|
101
|
+
describe "#check_dom_format!" do
|
102
|
+
it "TODO"
|
103
|
+
end #check_dom_format!
|
104
|
+
|
80
105
|
describe "#[]" do
|
81
106
|
it "returns the value in the named field" do
|
82
107
|
obj = MySubclass.create({'First' => 'Eric', 'Last' => 'Idle'})
|
83
108
|
obj['First'].should == 'Eric'
|
84
109
|
obj['Last'].should == 'Idle'
|
85
110
|
end
|
111
|
+
|
112
|
+
it "returns nil if the field doesn't exist" do
|
113
|
+
obj = MySubclass.create({'First' => 'Eric', 'Last' => 'Idle'})
|
114
|
+
obj['Middle'].should be_nil
|
115
|
+
end
|
86
116
|
end #[]
|
87
117
|
|
88
118
|
describe "#[]=" do
|
@@ -169,6 +199,11 @@ describe Cherby::BusinessObject do
|
|
169
199
|
@obj = MySubclass.new(xml)
|
170
200
|
end
|
171
201
|
|
202
|
+
it "checks the DOM format" do
|
203
|
+
@obj.should_receive(:check_dom_format!).and_return(true)
|
204
|
+
@obj.get_field_node('First')
|
205
|
+
end
|
206
|
+
|
172
207
|
it "returns the Field having the given Name" do
|
173
208
|
first_node = @obj.get_field_node('First')
|
174
209
|
first_node.should be_a(Nokogiri::XML::Node)
|
@@ -176,13 +211,44 @@ describe Cherby::BusinessObject do
|
|
176
211
|
first_node.inner_html.should == 'Eric'
|
177
212
|
end
|
178
213
|
|
179
|
-
it "
|
214
|
+
it "returns nil if the field doesn't exist" do
|
180
215
|
middle_node = @obj.get_field_node('Middle')
|
216
|
+
middle_node.should be_nil
|
217
|
+
end
|
218
|
+
end #get_field_node
|
219
|
+
|
220
|
+
describe "#get_or_create_field_node" do
|
221
|
+
before(:each) do
|
222
|
+
xml = %Q{
|
223
|
+
<BusinessObject Name="MySubclass">
|
224
|
+
<FieldList>
|
225
|
+
<Field Name="First">Eric</Field>
|
226
|
+
<Field Name="Last">Idle</Field>
|
227
|
+
</FieldList>
|
228
|
+
</BusinessObject>
|
229
|
+
}
|
230
|
+
@obj = MySubclass.new(xml)
|
231
|
+
end
|
232
|
+
|
233
|
+
it "checks the DOM format" do
|
234
|
+
@obj.should_receive(:check_dom_format!).and_return(true)
|
235
|
+
@obj.get_or_create_field_node('First')
|
236
|
+
end
|
237
|
+
|
238
|
+
it "returns the Field having the given Name" do
|
239
|
+
first_node = @obj.get_or_create_field_node('First')
|
240
|
+
first_node.should be_a(Nokogiri::XML::Node)
|
241
|
+
first_node.attr('Name').should == 'First'
|
242
|
+
first_node.inner_html.should == 'Eric'
|
243
|
+
end
|
244
|
+
|
245
|
+
it "creates a new Field if it doesn't exist" do
|
246
|
+
middle_node = @obj.get_or_create_field_node('Middle')
|
181
247
|
middle_node.should be_a(Nokogiri::XML::Node)
|
182
248
|
middle_node.attr('Name').should == 'Middle'
|
183
249
|
middle_node.inner_html.should == ''
|
184
250
|
end
|
185
|
-
end #
|
251
|
+
end #get_or_create_field_node
|
186
252
|
|
187
253
|
describe "#field_values" do
|
188
254
|
before(:each) do
|
data/spec/cherwell_spec.rb
CHANGED
@@ -77,22 +77,52 @@ describe Cherby::Cherwell do
|
|
77
77
|
it "returns a Cherby::Incident instance" do
|
78
78
|
incident_id = '51949'
|
79
79
|
incident_xml = File.read(File.join(DATA_DIR, 'incident.xml'))
|
80
|
+
@cherwell.stub(:last_error => nil)
|
80
81
|
@cherwell.stub(:get_object_xml).
|
81
82
|
with('Incident', incident_id).
|
82
83
|
and_return(incident_xml)
|
83
84
|
@cherwell.incident(incident_id).should be_a(Cherby::Incident)
|
84
85
|
end
|
86
|
+
|
87
|
+
it "raises Cherby::NotFound if incident is not found" do
|
88
|
+
incident_id = '99999'
|
89
|
+
empty_xml = File.read(File.join(DATA_DIR, 'empty.xml'))
|
90
|
+
@cherwell.stub(:get_object_xml).
|
91
|
+
with('Incident', incident_id).
|
92
|
+
and_return(empty_xml)
|
93
|
+
|
94
|
+
error = "Specified Business Object not found"
|
95
|
+
@cherwell.stub(:last_error => error)
|
96
|
+
lambda do
|
97
|
+
@cherwell.incident(incident_id)
|
98
|
+
end.should raise_error(Cherby::NotFound, /#{error}/)
|
99
|
+
end
|
85
100
|
end #incident
|
86
101
|
|
87
102
|
describe "#task" do
|
88
103
|
it "returns a Cherby::Task instance" do
|
89
104
|
task_id = '12345'
|
90
105
|
task_xml = File.read(File.join(DATA_DIR, 'task.xml'))
|
106
|
+
@cherwell.stub(:last_error => nil)
|
91
107
|
@cherwell.stub(:get_object_xml).
|
92
108
|
with('Task', task_id).
|
93
109
|
and_return(task_xml)
|
94
110
|
@cherwell.task(task_id).should be_a(Cherby::Task)
|
95
111
|
end
|
112
|
+
|
113
|
+
it "raises a Cherby::NotFound if task is not found" do
|
114
|
+
task_id = '99999'
|
115
|
+
empty_xml = File.read(File.join(DATA_DIR, 'empty.xml'))
|
116
|
+
@cherwell.stub(:get_object_xml).
|
117
|
+
with('Task', task_id).
|
118
|
+
and_return(empty_xml)
|
119
|
+
|
120
|
+
error = "Specified Business Object not found"
|
121
|
+
@cherwell.stub(:last_error => error)
|
122
|
+
lambda do
|
123
|
+
@cherwell.task(task_id)
|
124
|
+
end.should raise_error(Cherby::NotFound, /#{error}/)
|
125
|
+
end
|
96
126
|
end #task
|
97
127
|
|
98
128
|
describe "#get_object_xml" do
|
@@ -142,15 +172,6 @@ describe Cherby::Cherwell do
|
|
142
172
|
result = @cherwell.get_object_xml(@name, @public_id)
|
143
173
|
result.should == xml
|
144
174
|
end
|
145
|
-
|
146
|
-
it "raises a Cherby::SoapError if a Savon::Error occurs" do
|
147
|
-
soap_fault = Savon::Error.new("Kaboom")
|
148
|
-
@cherwell.client.stub(:call).and_raise(soap_fault)
|
149
|
-
lambda do
|
150
|
-
@cherwell.get_object_xml(@name, @public_id)
|
151
|
-
end.should raise_error(
|
152
|
-
Cherby::SoapError, /Kaboom/)
|
153
|
-
end
|
154
175
|
end #get_object_xml
|
155
176
|
|
156
177
|
describe "#update_object_xml" do
|
data/spec/data/empty.xml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
<?xml version="1.0"?>
|
data/spec/spec_helper.rb
CHANGED
@@ -3,7 +3,6 @@ require 'simplecov'
|
|
3
3
|
SimpleCov.start if ENV['COVERAGE']
|
4
4
|
|
5
5
|
require 'rspec'
|
6
|
-
require 'mustache'
|
7
6
|
|
8
7
|
ROOT_DIR = File.absolute_path(File.join(File.dirname(__FILE__), '..'))
|
9
8
|
LIB_DIR = File.join(ROOT_DIR, 'lib')
|
@@ -14,19 +13,23 @@ CONFIG_FILE = File.join(ROOT_DIR, 'config', 'test-config.yml')
|
|
14
13
|
CHERWELL_WSDL = File.join(DATA_DIR, 'cherwell.wsdl')
|
15
14
|
$LOAD_PATH.unshift(LIB_DIR)
|
16
15
|
|
17
|
-
class XMLTemplate < Mustache
|
18
|
-
self.template_path = XML_DIR
|
19
|
-
end
|
20
|
-
|
21
16
|
RSpec.configure do |config|
|
22
|
-
def xml_envelope(body)
|
23
|
-
return XMLTemplate.render_file('soap_envelope', :body => body)
|
24
|
-
end
|
25
|
-
|
26
17
|
def xml_response(method, body)
|
27
|
-
|
28
|
-
'
|
29
|
-
|
18
|
+
env_attrs = {
|
19
|
+
'xmlns:soap' => "http://schemas.xmlsoap.org/soap/envelope/",
|
20
|
+
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
|
21
|
+
'xmlns:xsd' => "http://www.w3.org/2001/XMLSchema",
|
22
|
+
}
|
23
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
24
|
+
xml['soap'].Envelope(env_attrs) do |env|
|
25
|
+
env.Body do
|
26
|
+
env.send(:"#{method}Response", 'xmlns' => 'http://cherwellsoftware.com') do
|
27
|
+
env.send(:"#{method}Result", body)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
return builder.to_xml
|
30
33
|
end
|
31
34
|
|
32
35
|
def savon_response(method, body)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cherby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-03-
|
12
|
+
date: 2014-03-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httpclient
|
@@ -75,22 +75,6 @@ dependencies:
|
|
75
75
|
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: mustache
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ! '>='
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: '0'
|
86
|
-
type: :runtime
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ! '>='
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0'
|
94
78
|
- !ruby/object:Gem::Dependency
|
95
79
|
name: rake
|
96
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -215,6 +199,7 @@ files:
|
|
215
199
|
- spec/cherwell_spec.rb
|
216
200
|
- spec/client_spec.rb
|
217
201
|
- spec/data/cherwell.wsdl
|
202
|
+
- spec/data/empty.xml
|
218
203
|
- spec/data/incident.xml
|
219
204
|
- spec/data/login_false.xml
|
220
205
|
- spec/data/login_true.xml
|
@@ -223,8 +208,6 @@ files:
|
|
223
208
|
- spec/journal_note_spec.rb
|
224
209
|
- spec/spec_helper.rb
|
225
210
|
- spec/task_spec.rb
|
226
|
-
- spec/xml/method_response_result.mustache
|
227
|
-
- spec/xml/soap_envelope.mustache
|
228
211
|
- tasks/pry.rake
|
229
212
|
- tasks/spec.rake
|
230
213
|
homepage: http://github.com/a-e/cherby
|
@@ -1,6 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
2
|
-
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
3
|
-
<soap:Body>
|
4
|
-
{{{body}}}
|
5
|
-
</soap:Body>
|
6
|
-
</soap:Envelope>
|