I am using SOAP::Lite to connect to an outside service. After much trial and error and communication with the other company, I have discovered the problem.
My code looks like this:
$soap = new SOAP::Lite
->service($wsdl_link)
->uri($url_link)
->proxy($proxy_link)
->on_action(sub { sprintf '"%s%s"', shift, shift });
my $resp = $soap->call('CreateAssignment',SOAP::Data->type('xml'=>$xml),
SOAP::Header->type('xml'=>$headXML));
This produces the following xml:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" >
<soap:Header>
...
</soap:Header>
<soap:Body>
<CreateAssignment xmlns="url_link">
...
</CreateAssignment></soap:Body></soap:Envelope>
(where url_link
is a valid url)
I need to define additional namespaces. I have done this by adding ->ns(namespace, prefix)
to my code. However, this adds the additional namespaces to the "envelope
" tag. I have been informed by the company that the namespaces need to be on the "CreateAssignment
" tag. Indeed, when I make the appropriate change and run it using SOAP UI, it works beautifully.
I have tried adding the "CreateAssignment
" tag to my xml and running the call()
function without a method. SOAP::Lite wraps the xml in a generic tag.
I have read the SOAP::Lite documentation, I have asked search engines, I have asked colleagues and no one has an answer.
Is there a way to force SOAP::Lite to put the namespace declarations where I need them?
If not, what is a better module to use?
I ended up sitting down with another coworker and reading the source code of SOAP::Lite - we discovered that the method tag was built in sub envelope
. There is an if-statement whereby the module will use the entire object if instead of a string object a SOAP::Data object is passed in as the method:
elsif (UNIVERSAL::isa($method => 'SOAP::Data')) {
$body = $method;
}
I changed from this:
$soap = new SOAP::Lite
->service($wsdl_link)
->uri($url_link)
->proxy($proxy_link)
->on_action(sub { sprintf '"%s%s"', shift, shift });
my $resp = $soap->call('CreateAssignment',SOAP::Data->type('xml'=>$xml),
SOAP::Header->type('xml'=>$headXML));
To this:
$method = SOAP::Data->new(name=>'ns4:CreateAssignment');
$method->attr({'xmlns'=> $namespaceOne,
'xmlns:ns2'=> $namespaceTwo,
'xmlns:ns3'=> $namespaceThree,
'xmlns:ns4'=> $namespaceFour,
'xmlns:ns5'=> $namespaceFive});
$soap = new SOAP::Lite
->service($wsdl_link)
->uri($url_link)
->proxy($proxy_link)
->on_action(sub { sprintf '"%s%s"', shift, shift });
my $resp = $soap->call($method,SOAP::Data->type('xml'=>$xml),
SOAP::Header->type('xml'=>$headXML));
This created my method tag exactly as the company required:
<ns4:CreateAssignment xmlns="namespaceOne" xmlns:ns2="namespaceTwo" xmlns:ns3="namespaceThree" xmlns:ns4="namespaceFour" xmlns:ns5="namespaceFive">
...
</ns4:CreateAssignment>