PHP SOAP XML attributes & namespaces with XMLWriter
January 3, 2012 - 3:39pm — brad
It has not worked on the three PHP installations I've tested it on, plus I needed to also specify namespaces. I decided I best go lower level, and looked into the SimpleXML class. Attributes are easy with SimpleXML, but attributes with namespaces aren't possible (Someone correct me if I am wrong.) So, I looked into the XMLWriter class and found exactly what I needed. The XMLWriter class gives you complete control over the XML creation, without have to write any XML yourself.
If the above function is called using: call_soap_wsdl('Search', 'SearchObj', 'FindUser', 123);, the resulting SOAP request (printed using print $client->__getLastRequest()) is:
If you've experienced the unending joy of attempting to make a PHP SOAP call using the SoapClass, you may have discovered XML node attributes cannot easily be created and passed. According to this comment: http://www.php.net/manual/en/soapvar.soapvar.php#101225 some people have had luck creating node attributes using the following code:
$amount['_'] = 25; $amount['currencyId'] = 'GBP'; $encoded = new SoapVar($amount, SOAP_ENC_OBJECT);
It has not worked on the three PHP installations I've tested it on, plus I needed to also specify namespaces. I decided I best go lower level, and looked into the SimpleXML class. Attributes are easy with SimpleXML, but attributes with namespaces aren't possible (Someone correct me if I am wrong.) So, I looked into the XMLWriter class and found exactly what I needed. The XMLWriter class gives you complete control over the XML creation, without have to write any XML yourself.
Here is the method I worked out for my use case and WSDL (code has been simplified, real thing is far more complex):
function call_soap_wsdl($method, $message, $operation, $important_id) { $xml = new XMLWriter(); $xml->openMemory(); $xml->startElementNS('objs', $method, 'ObjectNamespace'); // Send NULL to not specify the NameSpace on every call. $xml->startElementNS('objs', $message, NULL); //Attribute on a Namespaced node! $xml->writeAttribute('node-attribute', $operation); $xml->startElementNS('objs', 'ImportantId', NULL); $xml->Text($important_id); $xml->endElement(); $xml->endElement(); $xml->endElement(); //Convert it to a valid SoapVar $args = new SoapVar($xml->outputMemory(), XSD_ANYXML); $options = array( 'trace' => TRUE, 'soap_version' => SOAP_1_1, ); $wsdl = 'http:// example.com/service.wsdl'; $client = new SoapClient($wsdl, $options); try { $result = $client->__SoapCall($method, array($args)); } catch (Exception $e) { //Handle Exception - Use $client->__getLastRequestHeaders(), //$client->__getLastRequest(), $client->__getLastResponse(). $result = FALSE; } return $result; }
If the above function is called using: call_soap_wsdl('Search', 'SearchObj', 'FindUser', 123);, the resulting SOAP request (printed using print $client->__getLastRequest()) is:
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http ://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <objs:Search xmlns:objs="ObjectNamespace"> <objs:SearchObj operation="FindUser"> <objs:ImportantId>123</objs:ImportantId> </objs:SearchObj> </objs:Search> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Comments
Helped me loads, thanks!
Add new comment