2012-10-04 16 views
7

Estoy configurando un servicio web SOAP que toma entrada XML y tiene que devolver resultados XML personalizados. Todo esto se define en un WSDL. Aplico soapServer para esto (hasta que alguien dice que tiene errores que me impiden alcanzar mi objetivo :-)).¿Cómo devuelve una respuesta XML personalizada en la respuesta de soapServer?

No he podido devolver el XML personalizado: obtengo un resultado que parece estar basado en el WSDL, con un nombre de elemento raíz estándar igual al XML de entrada más "Respuesta". En realidad, eso también me sorprende, así que como pregunta complementaria, me pregunto por qué y si se puede influir. Por supuesto, es agradable que las definiciones WSDL se usen de alguna manera cuando se crean las respuestas, pero como dije, no sé cómo obtener un XML personalizado en la respuesta.

que llegaron hasta este:

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 de entrada

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

PHP actual

<?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(); 
?> 

XSLT utilizado anteriormente es sólo un cambio de un atributo - y cambio de temperatura el nombre de la raíz a la devuelta por el servidor siempre (por si acaso :-))

<?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> 

espero que el XML regreso a ser algo así como

<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> 

Pero en cambio es

<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> 

Depuración $ contenido dom en php anterior muestra exactamente el XML que trato de devolver (envuelto en Soap Envelope/Body, por supuesto, al igual que la entrada):

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

¿Dónde me equivoco? ¿Cómo obtener XML personalizado en el contenido de respuesta http devuelto?

Respuesta

7

¡Uf!

Esto me llevó varios intentos y buscar en Google hasta que descubrí lo que está mal.
Creo que se puede clasificar como un error en SoapVar.

Descubrí que aunque SoapVar es perfectamente capaz de analizar una cadena XML, no puede hacerlo si la cadena contiene una declaración XML como <?xml version="1.0" encoding="UTF-8"?>. Así que cuando tiene un DOMDocument o un SimpleXMLElement, primero tiene que quitar la declaración antes de analizar la cadena mediante SoapVar.

para un DOMDocument esto se puede hacer mediante la aplicación de saveXML con un parámetro igual a una variable DOMNode construido a partir de la propia dom, la elección de cualquier nodo, pero normalmente este será el nodo raíz, por supuesto.

En mi php del servidor, que añade el texto siguiente:

$nodes = $dom -> getElementsByTagName ('cdhead'); 
$node = $nodes -> item(0); 

$result = new SoapVar ($dom -> saveXML($node), XSD_ANYXML); 

Y ahora mi resultado es OK:

<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> 

En cuanto al nombre de la raíz del XML devuelto - estoy seguro de que lo haré ¡Descubre una forma de cambiar eso a lo que yo quiero que sea (en lugar de la respuesta estándar de mi102 generada por SoapVar)!

Cuestiones relacionadas