Php: Soap: How to add attribute to SoapVar
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.