2012-10-04 180 views
7

我正在設置一個SOAP webservice,它接受XML輸入並必須返回自定義XML輸出。 所有這些都是在WSDL中定義的。我爲此應用soapServer(直到有人說它有錯誤阻止我實現我的目標:-))。如何在soapServer響應中返回自定義XML響應?

我還沒有能夠返回自定義XML:我得到了一些似乎基於WSDL的結果,其標準根元素名稱等於輸入XML加上「Response」。 其實這讓我感到驚訝,所以作爲一個側面問題,我想知道這是爲什麼,它是否會受到影響。當然,創建響應時以某種方式使用WSDL定義是件好事,但正如我所說的,我不知道如何在響應中獲得自定義XML。

我得到儘可能的:

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

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

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

XSLT只是一個改變的屬性 - 和臨時變化根名稱服務器始終(:-)以防萬一)返回一個

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

我希望返回XML是像

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

但取而代之的則是

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

在上面的php中調試$ dom內容完全顯示了我嘗試返回的XML(當然,就像輸入的那樣,封裝在SOAP Envelope/Body中):

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

我該在哪裏出錯? 如何將自定義XML導入返回的http響應內容?

回答

7

唷!

這花了我幾次重試和谷歌搜索,直到我發現什麼是錯的。
我認爲它可以歸類爲SoapVar中的一個錯誤。

我發現儘管SoapVar完全能夠解析XML字符串,但如果字符串包含像<?xml version="1.0" encoding="UTF-8"?>這樣的XML聲明,它就不能這樣做。 因此,當您有DOMDocumentSimpleXMLElement時,首先必須在SoapVar解析字符串之前剝離聲明。

用於DOMDocument這可以通過施加saveXML具有等於從DOM本身構造的DOMNode可變的參數,選擇任何節點,但通常這將是當然的根節點來完成。

在我的服務器PHP中,我增加了以下內容:

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

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

現在我的結果是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> 

至於返回的XML的根名稱 - 我相信我會找到一種方法將其改變爲任何我想要的(而不是由SoapVar生成的標準mi102Response)!