views:

1454

answers:

3

Hello,

I'm trying to access a WebService using nuSOAP (because I'm bound to PHP4 here) that uses more than 1 namespace in a message. Is that possible?

An example request message would look like this:

<soapenv:Envelope ...
  xmlns:ns1="http://domain.tld/namespace1"
  xmlns:ns2="http://domain.tld/namespace2"&gt;
  <soapenv:Header/>
  <soapenv:Body>
    <ns1:myOperation>
      <ns2:Person>
        <ns2:Firstname>..</ns2:Firstname>
        ..
      </ns2:Person>
      <ns1:Attribute>..</ns1:Attribute>
    </ns1:myOperation>
  </soapenv:Body>
</soapenv:Envelope>

I tried to following:

$client = new nusoap_client("my.wsdl", true);
$params = array(
  'Person' => array(
    'FirstName'  => 'Thomas',
    ..
   ),
   'Attribute' => 'foo'
 );

 $result = $client->call('myOperation', $params, '', 'soapAction');

in the hope that nuSOAP would try to match these names to the correct namespaces and nodes. Then I tried to use soapval() to generate the elements and their namespace - but if I call an operation, nuSOAP creates the following request:

<SOAP-ENV:Envelope ...>
  <SOAP-ENV:Body>
    <queryCCApplicationDataRequest xmlns="http://domain.tld/namespace1"/&gt;
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

So something goes wrong during the "matching" phase.

+1  A: 

After trying around with the matching, I found two possible solutions:

1) Don't use the WSDL to create the nusoap_client and soapval() to create the message This has the disadvantage that the message contains a lot of overhead (the namespace is defined in each element). Not so fine.

2) Instead of relying on the matching of parameters, construct your reply in xml and put all the definition for prefixes in the first element - e.g.

$params = "<ns1:myOperation xmlns:ns1="..." xmlns:ns2="...">
      <ns2:Person>
        <ns2:Firstname>..</ns2:Firstname>
        ..
      </ns2:Person>
      <ns1:Attribute>..</ns1:Attribute>
    </ns1:myOperation>";

Still not a very nice solution, but it works :-)

wilth
I just tried your solution and it works....thanks man.
Ronald Conco
A: 

Yeah, i've been having this same problem (found your q via google!) and i've come across this: http://www.heidisoft.com/blog/using-nusoap-consume-net-web-service-10-min Here, the dev creates the xml body of the message in coe and then uses nusoap to submit.

Irwin
Hmm, seems the link is currently not working. From what you say, it seems they followed a similar approach (creating the xml "manually"), right?
wilth
A: 

Building on Irwin's post, I created the xml manually and had nusoap do the rest. My webhost does not have the php soap extension, so I had to go with nusoap, and the web service I'm trying to consume required the namespaces on each tag (e.g. on username and password in my example here).

require_once('lib/nusoap.php');

$client = new nusoap_client('https://service.somesite.com/ClientService.asmx');
$client->soap_defencoding = 'utf-8';
$client->useHTTPPersistentConnection(); // Uses http 1.1 instead of 1.0
$soapaction = "https://service.somesite.com/GetFoods";

$request_xml = '<?xml version="1.0" encoding="utf-8" ?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"&gt;
  <env:Body>
    <n1:GetFoods xmlns:n1="https://service.somesite.com"&gt;
      <n1:username>banjer</n1:username>
      <n1:password>theleftorium</n1:password>
    </n1:GetFoods>
  </env:Body>
</env:Envelope>
';

$response = $client->send($request_xml, $soapaction, ''); 

echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';

Then I had an error that said:

Notice: Undefined property: nusoap_client::$operation in ./lib/nusoap.php  on line 7674

So I went the lazy route and went into nusoap.php and added this code before line 7674 to make it happy:

    if(empty($this->operation)) {
        $this->operation = "";
    }
Banjer