Geniet van

XSD to PHP objects

Nothing can be more painfull than a SOAP service which does not return the full WSDL object descriptions. But there is a solution. Kind of ...

I recently got into one of these projects. I had to make a SOAP connection to an Enterprise Service Bus (ESB) which did have an incomplete WSDL description. The architects who designed this wanted to have a default service from which you could extract data from all kinds of systems. In this service, you deliver a servicename, which calls another service. However, they forgot the implications of this weird architecture. A PHP SOAP client can only do proper object mapping if it is described in the WSDL, otherwise you are screwed.

Here is an example of the SOAP request

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://some.url/question">
   <soapenv:Header/>
   <soapenv:Body>
      <ns1:Question>
         <ServiceName>theServiceName</ServiceName>
         <!-- Property can be multiple -->
         <Property Type="propertyType" Name="propertyName">
            <Value>propertyValue</Value>
         </Property>
      </ns1:Question>
   </soapenv:Body>
</soapenv:Envelope>

Pretty straight forward; The service is called 'Question'. It takes a property called 'ServiceName' and some other undefined properties, where the name itself is enclosed in the 'Name' attribute.

You can already guess how the response looks like

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <Answer Orchestration="theServiceName" xmlns="http://some.url/answer">
         <!-- Whatever comes in here has not been defined -->
      </Answer>
   </s:Body>
</s:Envelope>

Right, everything I get back from the WSDL is ... hold on ... tadaa, Answer.

All objects enclosed by Answer are not described in the WSDL. This means automated class mapping normally executed by the PHP SOAP client can't be done, because the SOAP client needs to know which property in the response needs to be mapped to which PHP object. And it gets its information partly from the WSDL.

Light on the horizon

However, one of the guys, responsible for the services from the ESB - not the architect, told me they could deliver the XSD's for all responses. Although I'm not religious, hallelujah!

That meant I could automatically generate all PHP objects and bind the XML properties from the response to these objects. But I had never done this before.

While searching the Internet I stumbled upon a project called Legko XML (XSD2PHP), started by a guy named Mike Bevz in 2010. The project handles the compiling of XSD to PHP objects and marshalling/unmarshalling XML. Marshalling is the process of transforming the representation of an object to a data format suitable for storage or transmission. Handling XML within PHP is sometimes a real pain in the ass, so the XML needs to be translated to PHP objects. The project looks old and unmaintained, but has 30 forks at the time of writing. 

Parts of this project I could use out of the box, like the automated class building from the XSD files. Some minor changes have been done for coding style and namespace directories of the generated PHP objects.

I was unlucky with other parts of the project, like binding XML to PHP objects. Arrays were not properly handled and the code quality was not exactly like I should do. But it gave me a very good start.

If you ever need to deal with this, have a look at Legko XML or one of its forks (when they derived from the original). It will give you a good start. 

PS. I know I need to make a pull request from my changes, but I need time for that.