2012-10-04 18 views
7

Sto configurando un servizio web SOAP che accetta l'input XML e deve restituire un output XML personalizzato. Tutto ciò è definito in un WSDL. Applico soapServer per questo (fino a quando qualcuno dice che ha bug che mi impediscono di raggiungere il mio obiettivo :-)).Come restituire la risposta XML personalizzata nella risposta soapServer?

non sono stato ancora in grado di restituire XML personalizzato: ho qualche risultato che sembra basarsi su teh WSDL, con un nome elemento radice standard pari a l'input XML uno più "Risposta". In realtà questo mi sorprende anche perché una domanda a parte mi chiedo perché sia ​​e se possa essere influenzata. Ovviamente è un aspetto positivo che le definizioni WSDL vengano utilizzate in qualche modo quando vengono create le risposte, ma come ho detto, non so come ottenere XML personalizzato nella risposta.

ho ottenuto fino a questo:

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

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

php corrente

<?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 utilizzato sopra è solo un cambiamento di un attributo - e cambiamento di temperatura il nome radice a quello restituito dal server sempre (solo nel caso :-))

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

mi aspetto il ritorno di XML per essere qualcosa di simile a

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

Ma invece è

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

Il debug di contenuti $ dom in php sopra mostra esattamente l'XML che provo a restituire (racchiuso in SOAP Envelope/Body, ovviamente, proprio come quello di input):

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

Dove posso andare storto? Come ottenere XML personalizzato nel contenuto della risposta HTTP restituita?

risposta

7

Phew!

Questo mi ha richiesto diversi tentativi e googling fino a quando ho scoperto cosa c'è che non va.
Penso che possa essere classificato come un bug in SoapVar.

Ho scoperto che mentre SoapVar è perfettamente in grado di analizzare una stringa XML, non può farlo se la stringa contiene una dichiarazione XML come <?xml version="1.0" encoding="UTF-8"?>. Quindi, quando si ha un DOMDocument o un SimpleXMLElement, si deve prima rimuovere la dichiarazione prima di analizzare la stringa con SoapVar.

per un DOMDocument questo può essere fatto applicando saveXML con un parametro uguale ad una variabile DOMNode costruito dal dom stessa, scegliendo qualsiasi nodo ma di solito questo sarà il nodo radice naturalmente.

Nel mio php assistente, ho aggiunto la seguente:

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

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

E ora il mio risultato è 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> 

Per quanto riguarda il nome radice del XML restituito - Sono sicuro che lo farò scopri un modo per cambiarlo a quello che voglio che sia (invece della mi102Response standard generata da SoapVar) !!

Problemi correlati