How to return custom XML response to soapServer response?

I am creating a SOAP web service that takes XML input and should return custom XML output. All of this is defined in the WSDL. I use soapServer for this (until someone says that he has errors that prevent me from reaching my goal :-)).

I have not yet been able to return custom XML: I get some result that seems to be based on WSDL, with a standard root element name equal to the input XML one plus "Response". In fact, this also surprises me, since the question on the side asks the question why this is so and what can be influenced. Of course, it’s good that the WSDL definitions are used somehow when answers are generated, but, as I said, I don’t know how to get custom XML in the response.

I got to this:

Wsdl

<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://pse/" xmlns:xs="http://www.w3.org/2001/XMLSchema" name="PSE" targetNamespace="http://pse/"> <types> <xs:schema> <xs:import namespace="http://pse/" schemaLocation="PSE.xsd"/> </xs:schema> </types> <message name="MI102Req"> <part name="cdhead" type="tns:cdhead_T"/> <part name="instr" type="tns:instr_T"/> </message> <message name="Res"> <part name="cdhead" type="tns:cdhead_T"/> </message> <portType name="MIPortType"> <operation name="mi102"> <input message="tns:MI102Req"/> <output message="tns:Res"/> </operation> </portType> <binding name="MIBinding" type="tns:MIPortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="mi102"> <soap:operation soapAction="http://www.testURL/test_soap.php#mi102"/> <input> <soap:body use="literal" namespace="http://pse/"/> </input> <output> <soap:body use="literal" namespace="http://pse/"/> </output> </operation> </binding> <service name="PSE"> <port name="MIPortType" binding="tns:MIBinding"> <soap:address location="http://www.testURL/test_soap.php"/> </port> </service> </definitions> 

XML input

 <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"> <Body> <mi102 xmlns="http://pse"> <cdhead version="13"/> <instr/> </mi102> </Body> </Envelope> 

current php

 <?php class PSE { function mi102 ($stdClassInput) { $inp = file_get_contents ('php://input'); $xml = simplexml_load_string ($inp); // Envelope $ch = $xml -> children (); $elt1 = $ch [0]; // Body $ch = $elt1 -> children (); $elt2 = $ch [0]; //mi102 $xslt = new XSLTProcessor(); $xslt -> registerPHPFunctions(); $xslt -> importStylesheet ( DOMDocument::load ('test.xslt') ); $dom = $xslt -> transformToDoc (DOMDocument::loadXML ($elt2 -> asXML())); $result = new SoapVar ($dom -> saveXML(), XSD_ANYXML); return ($result); } } ini_set( "soap.wsdl_cache_enabled", "0"); $server = new SoapServer ("test.wsdl"); $server -> setClass ('PSE'); $server -> setObject (new PSE()); $server -> handle(); ?> 

The XSLT used above is just an attribute change - and temp always changes the root name to the one returned by the server (just in case :-))

 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:pse="http://pse"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="pse:mi102"> <mi102Response> <xsl:apply-templates/> </mi102Response> </xsl:template> <xsl:template match="pse:cdhead"> <xsl:copy> <xsl:apply-templates select="@*"/> </xsl:copy> </xsl:template> <xsl:template match="@*"> <xsl:copy/> </xsl:template> <xsl:template match="@version"> <xsl:attribute name="version">14</xsl:attribute> </xsl:template> <xsl:template match="*"/> </xsl:stylesheet> 

I expect the returned XML to be something like

 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://pse/"> <SOAP-ENV:Body> <ns1:mi102Response> <cdhead version="14"/> </ns1:mi102Response> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 

But instead it is

 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://pse/"> <SOAP-ENV:Body> <ns1:mi102Response/> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 

Debugging the contents of $ dom in the above php shows exactly the XML I'm trying to return (wrapped in SOAP Envelope / Body, of course, as well as the input):

 <?xml version="1.0" encoding="UTF-8"?> <mi102Response xmlns:pse="http://pse"> <cdhead xmlns="http://pse" version="14"/> </mi102Response> 

Where am I mistaken? How to get custom XML in the returned content of an HTTP response?

+7
source share
1 answer

Phew!

It took me a few tries and googling until I discovered what was wrong. I think this can be attributed to a bug in SoapVar .

I found that although SoapVar is well versed in the XML string, it cannot do this if the string contains an XML declaration, for example <?xml version="1.0" encoding="UTF-8"?> . Therefore, when you have a DOMDocument or SimpleXMLElement , you must first disable the declaration before parsing the SoapVar string.

for a DOMDocument this can be done by applying saveXML with a parameter equal to the DOMNode variable built from the dom itself, selecting any node, but usually it will be the root of the node, of course.

On my php server, I added the following:

 $nodes = $dom -> getElementsByTagName ('cdhead'); $node = $nodes -> item(0); $result = new SoapVar ($dom -> saveXML($node), XSD_ANYXML); 

And now my result is fine:

 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://pse/"> <SOAP-ENV:Header/> <SOAP-ENV:Body> <ns1:mi102Response> <cdhead version="14"/> </ns1:mi102Response> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 

As for the root name of the returned XML - I'm sure I will find out a way to change it to what I want (instead of the standard mi102Response created by SoapVar) !!

+7
source

All Articles