I am attempting to create this output in PHP:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="http://webservices.company.co.uk/AddressMatching" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://webservices.company.co.uk/ServiceBase/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body>
<ns0:GetAvailableAddresses>
<ns0:request>
<ns2:UserCredentials>
<ns2:AgentID>123</ns2:AgentID>
<ns2:Password>PASSword</ns2:Password>
<ns2:Username>[email protected]</ns2:Username>
</ns2:UserCredentials>
<ns0:Address>
<ns0:PostCode>NG42DJ</ns0:PostCode>
</ns0:Address>
</ns0:request>
</ns0:GetAvailableAddresses>
</ns1:Body>
</SOAP-ENV:Envelope>
This is fairly easy in Python, the class I'm using (suds) simply reads the wsdl file, and uses the namespaces correctly:
from suds.client import Client
client = Client('/the/path/to/AddressMatchingService.wsdl')
creds = { 'AgentID': '123', 'Username': '[email protected]', 'Password': 'PASSword' }
address = client.factory.create('Address')
address.PostCode = "NG42DJ"
address_request = client.factory.create('AvailableAddressesRequest')
address_request.UserCredentials = creds
address_request.Address = address
request = client.service.GetAvailableAddresses(address_request)
print request
There is no need to reference anything to do with namespaces, it simply works by reading the wsdl file and figuring it out. As you can see in the original XML above, the variables have namespaces and inherit where required, also note that the Body is in the ns1 namespace.
The closest I have got in PHP, is using a WSDL-to-PHP converter which generates a ton of classes based on functions within the file, but it seems to lose all sense of namespacing by doing this. The only way of working with it I can see so far is to modify the generated class files like this:
// some code omitted...
use SoapVar; // added by me
// this is declared in AddressMatchingService namespace
class Credentials
{
public $AgentID = null;
public $Username = null;
public $Password = null;
public function __construct($AgentID, $Username, $Password)
{
//$this->AgentID = $AgentID;
$this->AgentID = new SoapVar($AgentID, null, null, null, null, "http://webservices.company.co.uk/ServiceBase/");
//$this->Username = $Username;
$this->Username = new SoapVar($Username, null, null, null, null, "http://webservices.company.co.uk/ServiceBase/");
//$this->Password = $Password;
$this->Password = new SoapVar($Password, null, null, null, null, "http://webservices.company.co.uk/ServiceBase/");
}
}
$wsdl = base_path() . '/resources/wsdl/AddressMatchingService.wsdl';
$soap = new SoapClient($wsdl, array('trace'=>1));
$creds = new AddressMatchingService\Credentials('123', '[email protected]','PASSword');
$address = new AddressMatchingService\Address('NG42DJ');
$request = array('request' => $request);
$request = new SoapVar($request, SOAP_ENC_OBJECT);
$response = $soap->__soapCall("GetAvailableAddresses", array('request' => $request));
Which gets me close-ish:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://webservices.company.co.uk/ServiceBase/" xmlns:ns2="http://webservices.company.co.uk/AddressMatching">
<SOAP-ENV:Body>
<ns2:GetAvailableAddresses>
<request>
<Address>
<PostCode>NG42DJ</PostCode>
</Address>
<ns1:UserCredentials>
<ns1:AgentID>123</ns1:AgentID>
<ns1:Password>PASSword</ns1:Password>
<ns1:Username>[email protected]</ns1:Username>
</ns1:UserCredentials>
<UPRN/>
</request>
</ns2:GetAvailableAddresses>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
But if it's so easy in Python, I thought I might be doing something wrong. Specifying the namespace in each class seems a pain, and I still don't know if it's possible to change the namespace of the Body from 'SOAP-ENV' to ns1. I would like to avoid handcrafting XML if I could avoid it, as there's so many functions and variables in the WSDL, I'd ideally like to make it work as efficiently as the Python suds library does!