7

XML 入力を受け取り、カスタム XML 出力を返す必要がある SOAP Web サービスをセットアップしています。これらはすべて WSDL で定義されます。これにsoapServerを適用します(誰かが私の目標を達成するのを妨げるバグがあると言うまで:-))。

私はまだカスタム XML を返すことができませんでした。入力 XML に "Response" を加えたものに等しい標準のルート要素名を持つ、WSDL に基づいていると思われる結果が得られます。実はそれには私も驚いているので、副次的な質問として、それがなぜなのか、影響を受けているのかどうか疑問に思っています。もちろん、応答を作成するときに 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 エンベロープ/ボディにラップされます)。

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

どこが間違っていますか?返された http 応答コンテンツにカスタム XML を取得するにはどうすればよいですか?

4

1 に答える 1

7

ふぅ!

これには、何が間違っているのかを発見するまで、何度か再試行してグーグルで検索する必要がありました。
のバグとして分類できると思いますSoapVar

SoapVar は XML 文字列を完全に解析できますが、文字列に<?xml version="1.0" encoding="UTF-8"?>. したがって、 aDOMDocumentまたは aがある場合はSimpleXMLElement、SoapVar で文字列を解析する前に、まず宣言を削除する必要があります。

これは、dom 自体から構築された変数に等しいパラメーターDOMDocumentを適用することで実行できます。任意のノードを選択しますが、通常はもちろんルート ノードになります。saveXMLDOMNode

私のサーバー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 の代わりに) 希望する名前に変更する方法が見つかると確信しています!!

于 2012-10-06T11:14:42.280 に答える