Emi R. Emi R. - 1 year ago 98
Perl Question

Define namespaces in the "method" element using SOAP::Lite

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?

Answer Source

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>
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download