Php: Soap: How to add attribute to SoapVar
Contents
Problem
The WSDL of a webservice requires me to provide an XML-attribute "version" when making a SOAP-call. See this WSDL snippet:
<complexType name="MessageHeader"> <sequence> <element name="From"/> <element name="To"/> </sequence> <attribute form="qualified" name="version" type="xsd:string" use="required"/>; </complexType>
But there is no way to specify attributes when I create a SoapVar like this(?):
$var = new StdClass; $var->From = 'foo'; $var->To = 'bar'; $MessageHeader = new SoapVar($var, SOAP_ENC_OBJECT);
The generated XML is not valid, because the `MessageHeader' element is missing the `version' attribute:
<ns2:MessageHeader> <From>foo</From> <To>bar</To> </ns2:MessageHeader>
Environment
- php-5.3.10
Solution 1: Element and attribute in same namespace
The solution is to map the WSDL object to a PHP class, and to specify the XML attribute as an object property. Now PHP will automatically create the XML attribute.
1. Map the WSDL object to a PHP class via the `classmap' option:
$client = new SoapClient(wsdl, array( 'trace' => 1, 'encoding' => 'UTF-8', 'soap_version' => SOAP_1_1, 'classmap' => array('MessageHeader' => 'MessageHeaderSoapStruct') ));
2. Create the PHP class:
class MessageHeaderSoapStruct { public $From; public $To; public $version; }
3. Create the SoapVar using the PHP class:
$var = new MessageHeaderSoapStruct; $var->From = 'foo'; $var->To = 'bar'; $var->version = 1; $namespace = 'http://xxx'; # Namespace of MessageHeader WSDL element $MessageHeader = new SoapVar($var, SOAP_ENC_OBJECT, 'MessageHeader', $namespace);
4. The generated XML now looks like this :)
<ns2:MessageHeader ns2:version="1"> <ns2:From>foo</ns2:From> <ns2:To>bar</ns2:To> </ns2:MessageHeader>
Solution 2: Element and attribute in different namespaces
In case the WSDL specifies the attribute in a different namespace:
<element name="element1" type="ns2:type1"/> ... <xsd:complexType name="type1"> <xsd:simpleContent> <xsd:extension base="xsd:string"> <xsd:attribute form="qualified" name="attribute1" type="xsd:string" use="required"/> </xsd:extension> </xsd:simpleContent> </xsd:complexType>
and the generated XML should look like this:
<ns1:element1 ns2:attribute1="myattribute1">myvalue1</ns1:element1>
Here's how to generate the XML:
1. Map the WSDL object containing the attribute (type1) to a PHP class via the `classmap' option:
$client = new SoapClient(wsdl, array( 'trace' => 1, 'encoding' => 'UTF-8', 'soap_version' => SOAP_1_1, 'classmap' => array( 'type1' => 'Type1SoapStruct' ) ));
2. Create the PHP class:
class Type1SoapStruct { public $attribute1; }
3. Create the SoapVar using the PHP class. Specify different namespaces for attribute1 and element1:
$nmB = 'http://mynamespace2'; $nsB = 'myns2'; $element1 = new Type1SoapStruct; $element1->attribute1 = new SoapVar('myattribute1', XSD_STRING, 'type1', null, $nmB, $nsB); $element1->_ = 'myvalue1'; $nmA = 'http://mynamespace1'; $nsA = 'myns1'; $element1_soapvar = new SoapVar($element1, SOAP_ENC_OBJECT, null, null, $nmA, $nsA); $params = new StdClass(); $params->element1 = $element1_soapvar; $this->__soapCall('mycall', array(new SoapVar(array($params), SOAP_ENC_OBJECT)));
4. The generated XML now looks like this :)
<ns1:element1 ns2:attribute1="myattribute1" xsi:type="ns2:type1">myvalue1</ns1:element>
Journal
20150917
- [SOLVED] php Soap Client - Node Attributes
- Forum thread with the classmap solution
- Creating a SOAP request with PHP - how do I add attributes to the XML tags? - Stack Overflow:
- Forum thread with a workaround using the XSD_ANYXML encoding.