2012-10-04 125 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)!