Re: PEAR::SOAP - Nested complex types - Is it possible?
| From: | Michele Manzato | Date: | Fri, 11 Jul 2003 09:31:24 +0000 |
| Subject: | Re: PEAR::SOAP - Nested complex types - Is it possible? | ||
| References: | 1 | Groups: | php.soap |
| Request: | Send a blank email to php-soap+get-774@lists.php.net to get a copy of this message | ||
Hi,
(I apologise for not being very short...)
I bumped into kind of a similar problem. Basically, the SOAP service I am
implementing sends forth and back quite complex tree-like structures (it's
an address search & route planning web service: structs containing structs
and arrays that, in turn, contain structs...).
These types are handled quite OK by the WSDL generation routines (thank you
all who did this great job) by using the "$soapclass->__typedef[]"
associative array, e.g:
$soapclass->__typedef['{urn:myWebService}CoordinatesType'] =
array('Longitude' => 'float',
'Latitude' => 'float');
$soapclass->__typedef['{urn:myWebService}AddressMatchType'] =
array('Town' => 'string',
'Address' => 'string',
'Coordinates' => '{urn:myWebService}CoordinatesType');
... and so on. Also, service ports (methods) are correctly rendered in WSDL
as long as I define them in the "$soapclass->__dispatch_map[]" associative
array, e.g.:
$soapclass->__dispatch_map['findAddress'] =
array('in' => array('address' =>
'{urn:myWebService}AddressSearchType'),
'out' => array('result' => 'boolean',
'match' =>
'{urn:myWebService}AddressMatchType') );
So, if I may answer to Bruno, almost everything which is needed to generate
arbitrarily complex WSDLs should be there (nillable items are an
exception... see my other post).
The problem comes when doing type translation, e.g. mapping (XML elements in
the SOAP message) <=> (PHP class instances). AFAIK, type translation should
be enabled via "$soapBaseObject->__set_type_translation()", (where
$soapBaseObject is either the $server or the $client), that is e.g.:
$soapBaseObject->__set_type_translation('{urn:myWebService}AddressMatchType'
, 'PhpClass_AddressMatch');
$soapBaseObject->__set_type_translation('{urn:myWebService}CoordinatesType',
'PhpClass_Coordinates');
I noted that type translation works nice XML -> PHP, but PHP -> XML there
are some problems. Namely, if the findAddress function above returns:
function findAddress(...) {
...
$match = new PhpClass_AddressMatch;
$match->Town = "London";
$match->Address = "Queens Crescent, 10";
$match->Coordinates = new PhpClass_Coordinates;
$match->Coordinates->Longitude = 11.7654321;
$match->Coordinates->Latitude = 45.1234567;
return array(true, $match);
}
the body of the response SOAP message produced will be:
<SOAP-ENV:Body>
<ns4:findAddressResponse>
<result xsi:type="xsd:boolean">true</result>
<match xsi:type="ns4:AddressMatchType">
<Town xsi:type="xsd:string">London</Municipality>
<Address xsi:type="xsd:string">Queens Crescent, 10</Address>
<Coordinates> [*********]
<Longitude xsi:type="xsd:float">11.7654321</Longitude>
<Latitude xsi:type="xsd:float">45.1234567</Latitude>
</Coordinates>
</match></ns4:findAddressResponse>
</SOAP-ENV:Body>
As you can see, the [*********] element misses the "xsi:type" specification
(isn't it required in "Section5 encoding"?). I had a look into the code, and
I expect that with anything nested deeply than the first level the SOAP
serializer behaves the same. The real problem comes when the SOAP client
tries to parse the response (remember that it also knows about type
mappings): in fact it maps quite correctly the AddressMatchType to a
PhpClass_AddressMatch, but it fails to map the Coordinates to a
PhpClass_Coordinates since it has no knowledge of this element's type.
Eventually a phpClass object is created instead.
Ok, I know I could use SOAP_Value to force the serialization of the right
type, but that's not really "automatic" type mapping.
Some other feelings & experiences?
Regards
Michele
----------------------------------------------------------------------------
-----------
"Gendron Bruno" <b.gendron@umontreal.ca> ha scritto nel messaggio
news:B5835E1CC5947D4F81BEAE6C6997398F8A159D@etna.sim.umontreal.ca...
Hi,
Supposing a web service that would return a message element of type
FeatureCollection containing an array of elements (ArrayofFeatures) of type
Feature, as defined in the WSDL snippet below:
<types xmlns="http://schemas.xmlsoap.org/wsdl/">
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://mynamespace.net">
<complexType name="FeatureCollection">
<sequence>
<element name="count" type="xsd:int"
<element name="features" type="ArrayOfFeatures" />
</sequence>
</complexType>
<complexType name="ArrayOfFeatures">
<complexContent>
<restriction base="SOAP-ENC:arrayType">
<attribute ref="SOAP-ENC:arrayType" arrayType="Feature[]" />
</restriction>
</complexContent>
</complexType>
<complexType name="Feature">
<sequence>
<element name="distance" type="xsd:float" />
<element name="x" type="xsd:float" />
<element name="y" type="xsd:float" />
</sequence>
</complexType>
</schema>
</types>
Is the PEAR::SOAP implementation capable of handling such complex types? If
not, I would have to rely on some other SOAP implementation...
If so, how would you proceed to define such element types in the server in
order to use PEAR::SOAP WSDL generation capabilities (I have looked carefuly
through the examples and documentation, without being able to figure out)?
Also, how would you create such a FeatureCollection element in order to be
able to send it back from the PHP server? I understand the process for
simple types (return $somestring;) of "simple" complex types, but for nested
complex types?
Many thanks...
----
Bruno Gendron
Conseiller scientifique - Spécialiste en géomatique / Advisor - GIS
Specialist
Chaire de recherche du Canada en études asiatiques / Canada Chair of Asian
Research
Université de Montréal
3477, rue Jean-Brillant, bureau 530-26
C.P. 6128, Succ. Centre-ville
Montréal, QC, Canada, H3C 3J7
Tél : +1 514-343-5768
Fax (CETASE) : +1 514-343-7716
Web : http://www.caac.umontreal.ca