【问题标题】:How return custom XML response in soapServer response?如何在soapServer 响应中返回自定义XML 响应?
【发布时间】:2012-10-04 22:03:03
【问题描述】:

我正在设置一个接受 XML 输入并且必须返回自定义 XML 输出的 SOAP Web 服务。 所有这些都在 WSDL 中定义。我为此应用了soapServer(直到有人说它存在阻止我实现目标的错误:-))。

我还不能返回自定义 XML:我得到了一些似乎基于 WSDL 的结果,其标准根元素名称等于输入 XML 加“响应”。 实际上,这也让我感到惊讶,所以作为一个附带问题,我想知道为什么会这样以及它是否会受到影响。当然,在创建响应时以某种方式使用 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 响应内容中?

【问题讨论】:

    标签: php soap soapserver


    【解决方案1】:

    呼!

    这花了我几次重试和谷歌搜索,直到我发现出了什么问题。
    我认为它可以归类为SoapVar 中的错误。

    我发现虽然 SoapVar 完全能够解析 XML 字符串,但如果字符串包含像 &lt;?xml version="1.0" encoding="UTF-8"?&gt; 这样的 XML 声明,它就不能这样做。 因此,当您有DOMDocumentSimpleXMLElement 时,您首先必须在SoapVar 解析字符串之前去掉声明。

    对于DOMDocument,这可以通过应用saveXML 来完成,其参数等于从dom 本身构造的DOMNode 变量,选择任何节点,但通常这当然是根节点。

    在我的服务器 php 中,我添加了以下内容:

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

    现在我的结果还可以:

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

    【讨论】:

      猜你喜欢
      • 2012-09-28
      • 2021-07-13
      • 2020-04-23
      • 2019-10-28
      • 1970-01-01
      • 2021-05-10
      • 2017-03-26
      • 1970-01-01
      • 2021-01-08
      相关资源
      最近更新 更多