If you are trying to integrate with Magento using the v2 API in WS-I compliance mode, you’re going to soon realise that any additional attributes you specify when calling the catalogProductCreate method are not going to show up in the product you create; as I so frustratingly found out after a good few hours of debugging!

The reason for this is due to a mistake that has been made in the WSDL for the WS-I compliant API. The definition of the additional_attributes element in the non WS-I compliant API (i.e. the one that doesn’t suffer from this problem) is as follows:

<element name="additional_attributes" type="typens:catalogProductAdditionalAttributesEntity" minOccurs="0"/>


However, in the WS-I compliant WDSL, the definition is:

<xsd:element name="additional_attributes" type="typens:associativeArray" minOccurs="0">
</xsd:element>


The latter will generate XML which contains an array of associative entities within the additional_attributes element, as per the extract below:

<additional_attributes>
<complexObjectArray>
<key>
shipping_international_economy
</key>
<value>
10.0000
</value>
</complexObjectArray>
<complexObjectArray>
<key>
shipping_rm_europe_sign
</key>
<value>
10.0000
</value>
</complexObjectArray>
<complexObjectArray>
<key>
shipping_rm_international_sign
</key>
<value>
12.0000
</value>
</complexObjectArray>


How this should actually appear is with a single_data or multi_data element as a direct child of the additional_attributes element.

Below is a snippet from the file that handles the API requests (found in app/code/core/Mage/Catalog/Model/Product/Api/V2.php on line 250) which deals with parsing the additional attributes:

if (property_exists($productData, 'additional_attributes')) { if (property_exists($productData->additional_attributes, 'single_data')) {
foreach ($productData->additional_attributes->single_data as$_attribute) {
$_attrCode =$_attribute->key;
$productData->$_attrCode = $_attribute->value; } } if (property_exists($productData->additional_attributes, 'multi_data')) {
foreach ($productData->additional_attributes->multi_data as$_attribute) {
$_attrCode =$_attribute->key;
$productData->$_attrCode = $_attribute->value; } } unset($productData->additional_attributes);
}


As you can see, if the single_data or multi_data elements do not exist, it simply discards the data we pass to it.

In order to make this work with the WS-I compliant API, we simply need to add a third if statement to the above code to make it recognise there being an array of entities as a child of additional_attributes, which makes the above block look like this:

if (property_exists($productData, 'additional_attributes')) { if (property_exists($productData->additional_attributes, 'single_data')) {
foreach ($productData->additional_attributes->single_data as$_attribute) {
$_attrCode =$_attribute->key;
$productData->$_attrCode = $_attribute->value; } } if (property_exists($productData->additional_attributes, 'multi_data')) {
foreach ($productData->additional_attributes->multi_data as$_attribute) {
$_attrCode =$_attribute->key;
$productData->$_attrCode = $_attribute->value; } } if (gettype($productData->additional_attributes) == 'array') {
foreach ($productData->additional_attributes as$k => $v) {$_attrCode = $k;$productData->$_attrCode =$v;
}
}