typemap-Parameter: XML <-> Objekt

Der Typemap-Parameter von PHPs SoapClient ist nicht sonderlich gut dokumentiert. Tatsächlich fand ich die einzigen vernünftigen Anwendungsbeispiele unter PHPs Unit-Tests.

Der typemap-Parameter dient dem Mapping zwischen XML-Elementen und korrespondierenden Objekten. Dazu wird eine oder zwei Callbackfunktionen definiert, die jeweils die Umwandlung vom XML-Element zu Objekt (from_xml) bzw. umgekehrt (to_xml) handhaben.

Ein allgemeines Beispiel für die typemap-Parameterübergabe, die im Optionen-paramter des SoapClients stattfindet, sieht so aus:

Ein Anwendungsbeispiel

Das Problem

Die Aufgabe war, ein komplexes Datenobjekt abzufragen, es zu modifizieren und wieder zurückzuschreiben.
Hier ist der relevante Ausschnitt aus dem WSDL, mit dem ich zu tun hatte:

Zu welchem konkreten Typ das XML-Element nun gehörte (attributeNumber oder attributeVarchar2) wurde ihm als type-Attribute mitgegeben. Diese Information ging aber vollkommen verloren. Wenn der SoapClient dann das Objekt, das diese Daten enthielt, zurück in XML schrieb, orientierte er sich natürlich nur am attribute-Typ. D.h. der attributeName wurde übergeben, aber der attributeValue nicht. Das führte zu Problemen, weil wichtige und notwendige Informationen fehlten.

Der Lösungsansatz

Irgendwie musste attributeValue und Typ wieder zurück in den Service-Request. Nach einigem Herumprobieren und Herumgooglen fiel die Wahl auf – ihr habt’s geahnt – den Typemap-Parameter.

Die über den Key from_xml hinterlegte Callbackfunktion erhält automatisch das betreffende XML-Element in String-Form, der dann ausgewertet werden kann. Was ich hier tat, war das type-Attribut des XML-Elementes auszulesen und zusammen mit den restlichen Kind-Elementen als Eigenschaften des Objektes anzulegen.

Beim Zurückschreiben kommt dann die Callbackfunktion für to_xml ins Spiel.

Allerdings waren ein paar Fallstricke zu beachten.

Für gewöhnlich, ist es am Einfachsten ein multidimensionales Objekt als multidimensionales Array an den SOAP-Service zu übergeben. In diesem Fall funktionierte es jedoch nicht, weil die Callback-Funktion, die zurück ins XML schreibt, ein Objekt benötigt. Daher wurden alle FlexAttribut-Objekte innerhalb des Arrays in SoapVars umgewandelt. Ohne diese Umwandlung funktionierte es nicht. Erst dann wurde die Callback-Funktion auch aufgerufen.

Mit diesen Einstellungen und Funktionen klappte es dann, dass verschachtelte Datenobjekt zurück an den Service zu übergeben.

Anmerkung

Ein Punkt, der mir aufgefallen war:

Obwohl in der flexToXml()-Funktion auch für die Kind-Elemente das Präfix ‚entity‘ vorgesehen war, wurde es bei der Umsetzung in den Service-Request aus den Kind-Elementen entfernt. Ich vermute, dass ich das hätte lösen können, indem ich auch für die Kind-Elemente ein Type-Mapping implementiere.

Dazu kam es nicht, weil die uns gegebene WSDL aus anderen Gründen geändert werden musste. Dabei wurde auch diese mehrdeutige Typendefinition der flexAttribute überarbeitet. Dieser Code hier wurde damit überflüssig.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.