Форматирование ответов PHP Soap Server

Я делаю веб-службу SOAP на PHP, которая должна соответствовать требованиям XSD-файла клиента.

Вот ссылка на файл XSD, предоставленный клиентом: http://pastebin.com/MX1BZUXc

Ответ, который они ожидают, выглядит следующим образом:

[Некоторые длинные строки разбиты на разборчивость, на теорию о том, что проблема не связана с пробелами.]

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Header /> <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <CheckVersionResponse xmlns="http://www.---.---/---"> <CheckversionResult> <ValidationOk>true</ValidationOk> <VersionNumber>1.4.0</VersionNumber> <CurrentRemoteServerTime >2014-05-02T09:35:20.368+02:00</CurrentRemoteServerTime> </CheckversionResult> </CheckVersionResponse> </s:Body> </s:Envelope> 

Однако ответ, который я сейчас получаю, выглядит следующим образом:

 <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://---.---/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://www.w3.org/2003/05/soap-encoding"> <env:Body xmlns:rpc="http://www.w3.org/2003/05/soap-rpc"> <ns1:CheckVersionResponse env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"> <rpc:result>return</rpc:result> <return xsi:type="enc:Struct"> <ValidationOk xsi:type="xsd:int">1</ValidationOk> <VersionNumber xsi:type="xsd:string" >1.4.0</VersionNumber> <CurrentRemoteServerTime xsi:type="xsd:string" >2014-05-08T10:31:49</CurrentRemoteServerTime> </return> </ns1:CheckVersionResponse> </env:Body> </env:Envelope> 

Вот как я сделал веб-сервис SOAP:

 <?php /* Helper class for my response object */ class CheckVersionResult extends stdClass { /** @var bool */ public $ValidationOk = ''; /** @var string */ public $VersionNumber = ''; /** @var string */ public $CurrentRemoteServerTime = ''; } /* SOAP interface class */ class MySoapClass { /** * Returns version * * @param string $param1 * @param string $param2 * @return CheckVersionResult */ public function CheckVersion($param1, $param2) { $data = new CheckVersionResult(); $data->ValidationOk = 1; $data->VersionNumber = '1.4.0'; $data->CurrentRemoteServerTime = date('Ymd\TH:i:s'); } } /* Controller class */ class WebserviceController { public function indexAction() { $soap = new Zend_Soap_Server(); $soap->setClass('MySoapClass'); $soap->setUri("http://---.---/"); $mySoapClass = new MySoapClass(); $soap->setObject($mySoapClass); $soap->setSoapVersion(SOAP_1_2); $soap->handle(); } } 

И так я называю свой веб-сервис:

 $client = new SoapClient(null, array( "soap_version" => SOAP_1_2, "location" => "http://---.---/webservice/index", "uri" => "http://---.---/", "trace" => 1, // enable trace to view what is happening "exceptions" => 0, // disable exceptions "cache_wsdl" => 0) // no wsdl ); $client->CheckVersion('param1', 'param2'); header('Content-Type: application/xml; charset=utf-8'); echo $client->__getLastResponse(); die(); 

Кто-нибудь знает, как я могу правильно отформатировать SOAP-ответ в соответствии с файлом XSD, который я получил?

Вы должны создать правильный файл wsdl. Сейчас ваш сервер работает в стиле rpc по умолчанию. Попробуйте использовать: http://framework.zend.com/manual/1.12/en/zend.soap.autodiscovery.html с различными стилями привязки WSDL.

Что-то вроде этого:

server.php:

 <?php error_reporting(E_ALL); ini_set('display_errors', 1); set_include_path(get_include_path().';./library/;./library/Zend'); require_once 'Zend/Loader/Autoloader.php'; $autoloader = Zend_Loader_Autoloader::getInstance(); $autoloader->setFallbackAutoloader(true); /* Helper class for my response object */ class CheckVersionResult extends stdClass { /** @var bool */ public $ValidationOk = ''; /** @var string */ public $VersionNumber = ''; /** @var string */ public $CurrentRemoteServerTime = ''; } /* SOAP interface class */ class MySoapClass { /** * Returns version * * @param string $param1 * @param string $param2 * @return CheckVersionResult */ public function CheckVersion($param1, $param2) { $data = new CheckVersionResult(); $data->ValidationOk = 1; $data->VersionNumber = '1.4.0'; $data->CurrentRemoteServerTime = date('Ymd\TH:i:s'); return $data; } } $mySoapClass = new MySoapClass(); if(isset($_GET['wsdl'])) { $autodiscover = new Zend_Soap_AutoDiscover(); $autodiscover->setClass('MySoapClass'); $autodiscover->setOperationBodyStyle( array('use' => 'literal', 'namespace' => 'http://localhost/stack/23537231/server.php') ); $autodiscover->setBindingStyle( array('style' => 'document', 'transport' => 'http://localhost/stack/23537231/server.php') ); $autodiscover->handle(); } else { // pointing to the current file here $soap = new Zend_Soap_Server("http://localhost/stack/23537231/server.php?wsdl", array( 'cache_wsdl'=> WSDL_CACHE_NONE, 'classmap' => array( 'CheckVersionResult'=>'CheckVersionResult', ) )); $soap->setClass('MySoapClass'); $soap->handle(); } 

client.php

 <?php error_reporting(E_ALL); ini_set('display_errors', 1); set_include_path(get_include_path().';./library/;./library/Zend'); require_once 'Zend/Loader/Autoloader.php'; $autoloader = Zend_Loader_Autoloader::getInstance(); $autoloader->setFallbackAutoloader(true); /* Helper class for my response object */ class CheckVersionResult extends stdClass { /** @var bool */ public $ValidationOk = ''; /** @var string */ public $VersionNumber = ''; /** @var string */ public $CurrentRemoteServerTime = ''; } $client = new SoapClient('http://localhost/stack/23537231/server.php?wsdl', array( "trace" => 1, // enable trace to view what is happening "exceptions" => 1, // disable exceptions "cache_wsdl" => WSDL_CACHE_NONE, 'classmap' => array( 'CheckVersionResult'=>'CheckVersionResult', )) // no wsdl ); $ret = $client->CheckVersion('param1', 'param2'); header('Content-Type: application/xml; charset=utf-8'); echo $client->__getLastResponse(); die(); 

С этим я имею это:

 <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns1:CheckVersionResponse> <return xsi:type="ns1:CheckVersionResult"> <ValidationOk xsi:type="xsd:boolean">true</ValidationOk> <VersionNumber xsi:type="xsd:string">1.4.0</VersionNumber> <CurrentRemoteServerTime xsi:type="xsd:string">2014-05-19T22:22:59</CurrentRemoteServerTime> </return> </ns1:CheckVersionResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 

Боковое замечание: я думаю, что ваш ответ является действительным ответом на мыло. Поэтому, если клиент является действительным клиентом soap, он должен иметь возможность анализировать ответ и все еще использовать его.