PHP从SOAP客户端解析SOAP XML响应

时间:2014-05-08 00:10:12

标签: php json web-services soap wsdl

我通过php向外部Web服务进行SOAP调用。我终于有了它的工作。最后一步是解析SOAP服务的响应。

当我这样做时:

echo '{"reference": "'.$client->__getLastResponse().'", "success":"true"}';

我希望得到并且我看到HTML网页响应:

{"reference": "000002R5281191606961", "success":"true"}

然而,当我查看开发人员工具源/预览时,我看到了:

{"reference": "<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetPaynetReferenceResponse xmlns="http://www.paynet.com.mx/"><GetPaynetReferenceResult><RespCode>0</RespCode><RespDesc /><PaynetReference>00002R5281191606961</PaynetReference></GetPaynetReferenceResult></GetPaynetReferenceResponse></soap:Body></soap:Envelope>", "success":"true"} 

我需要的变量就是大量的XML内容!我怎样才能拉出所需的变量,并将其作为json返回?

如果有帮助,请点击这里:

$wsdl = 'http://201.147.99.51//PaynetCE/WSPaynetReference.asmx?WSDL';
$trace = true;
$exceptions = false;

$client = new SoapClient($wsdl, array('trace' => $trace, 'exceptions' => $exceptions));
$response = $client->__soapCall("GetPaynetReference", array($data));

echo"<pre>";
print_r($client);
echo"</pre>";
echo"<pre>";
print_r($client->__last_response);
echo"</pre>";

这一切似乎都有效,我在html / php页面中得到以下输出:

SoapClient Object
(
    [trace] => 1
    [_exceptions] => 
    [_soap_version] => 1
    [sdl] => Resource id #2
    [__last_request] => 
3c090569-1044-48a8-9bc3-de3c8db22a80Recarga tu saldo Elepago.NUMCLIENTE528119160696

    [httpsocket] => Resource id #3
    [_use_proxy] => 0
    [httpurl] => Resource id #4
    [__last_request_headers] => POST /PaynetCE/WSPaynetReference.asmx HTTP/1.1
Host: 201.147.99.51
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.4.4
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://www.paynet.com.mx/GetPaynetReference"
Content-Length: 626


    [__last_response_headers] => HTTP/1.1 200 OK
Date: Wed, 07 May 2014 23:57:45 GMT
Server: Microsoft-IIS/6.0
X-UA-Compatible: IE=EmulateIE7
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Content-Length: 478

    [__last_response] => 000002R5281122606961
)
000002R5281122606961

__last_response是我需要的代码。我试图将其作为JSON发送。

当我在页面的预览/来源查看开发人员工具时,我得到了这个:

 <pre>SoapClient Object
(
    [trace] => 1
    [_exceptions] => 
    [_soap_version] => 1
    [sdl] => Resource id #2
    [__last_request] => <?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.paynet.com.mx/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><SOAP-ENV:Body><ns1:GetPaynetReference><ns1:issuerCod>3c090569-1044-48a8-9bc3-de3c8db22a80</ns1:issuerCod><ns1:description>Recarga tu saldo Elepago.</ns1:description><ns1:params><ns1:Parameter><ns1:Name>NUMCLIENTE</ns1:Name><ns1:Value xsi:type="xsd:string">528119160696</ns1:Value></ns1:Parameter></ns1:params></ns1:GetPaynetReference></SOAP-ENV:Body></SOAP-ENV:Envelope>

    [httpsocket] => Resource id #3
    [_use_proxy] => 0
    [httpurl] => Resource id #4
    [__last_request_headers] => POST /PaynetCE/WSPaynetReference.asmx HTTP/1.1
Host: 201.147.99.51
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.4.4
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://www.paynet.com.mx/GetPaynetReference"
Content-Length: 626


    [__last_response_headers] => HTTP/1.1 200 OK
Date: Wed, 07 May 2014 23:57:45 GMT
Server: Microsoft-IIS/6.0
X-UA-Compatible: IE=EmulateIE7
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Content-Length: 478

    [__last_response] => <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetPaynetReferenceResponse xmlns="http://www.paynet.com.mx/"><GetPaynetReferenceResult><RespCode>0</RespCode><RespDesc /><PaynetReference>00002R5281191606961</PaynetReference></GetPaynetReferenceResult></GetPaynetReferenceResponse></soap:Body></soap:Envelope>
)
</pre><pre><?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetPaynetReferenceResponse xmlns="http://www.paynet.com.mx/"><GetPaynetReferenceResult><RespCode>0</RespCode><RespDesc /><PaynetReference>00002R5281191606961</PaynetReference></GetPaynetReferenceResult></GetPaynetReferenceResponse></soap:Body></soap:Envelope></pre> 

2 个答案:

答案 0 :(得分:2)

使用SimpleXMLElement::xpath方法和以下路径......

/soap:Envelope/soap:Body/a:GetPaynetReferenceResponse/a:GetPaynetReferenceResult/a:PaynetReference/text()
使用SimpleXMLElement::registerXPathNamespace注册以下名称空间前缀后

Prefix    Namespace
------    ---------
xsi       http://www.w3.org/2001/XMLSchema-instance
xsd       http://www.w3.org/2001/XMLSchema
soap      http://schemas.xmlsoap.org/soap/envelope/
xml       http://www.w3.org/XML/1998/namespace
a         http://www.paynet.com.mx/

采用这种方法,转换......

echo '{"reference": "'.$client->__getLastResponse().'", "success":"true"}';

......如下:

$xml = new SimpleXMLElement($client->__getLastResponse());
$xml->registerXPathNamespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance');
$xml->registerXPathNamespace('xsd', 'http://www.w3.org/2001/XMLSchema');
$xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
$xml->registerXPathNamespace('xml', 'http://www.w3.org/XML/1998/namespace');
$xml->registerXPathNamespace('a', 'http://www.paynet.com.mx/');
$xpath = '/soap:Envelope/soap:Body/a:GetPaynetReferenceResponse/a:GetPaynetReferenceResult/a:PaynetReference/text()';

$result = $xml->xpath($xpath);
if ($result != FALSE && count($result) > 0) {
    echo '{"reference": "' . $result[0] . '", "success":"true"}';
} else {
    // TODO: Whatever....
}

修改

为了清楚地了解我如何检查这个解决方案,这里是我所描绘的PoC,而不能使用$client->__getLastResponse()本身:

<html>
<head><title>PoC Page</title></head>

<body>
<?php
// FORNOW - Use $lastResponse since I can't really use $client->__getLastResponse() for a PoC.
$lastResponse = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetPaynetReferenceResponse xmlns="http://www.paynet.com.mx/"><GetPaynetReferenceResult><RespCode>0</RespCode><RespDesc /><PaynetReference>00002R5281191606961</PaynetReference></GetPaynetReferenceResult></GetPaynetReferenceResponse></soap:Body></soap:Envelope>';
$xml = new SimpleXMLElement($lastResponse);
//$xml = new SimpleXMLElement($client->__getLastResponse());
$xml->registerXPathNamespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance');
$xml->registerXPathNamespace('xsd', 'http://www.w3.org/2001/XMLSchema');
$xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
$xml->registerXPathNamespace('xml', 'http://www.w3.org/XML/1998/namespace');
$xml->registerXPathNamespace('a', 'http://www.paynet.com.mx/');
$xpath = '/soap:Envelope/soap:Body/a:GetPaynetReferenceResponse/a:GetPaynetReferenceResult/a:PaynetReference/text()';

$result = $xml->xpath($xpath);
if ($result != FALSE && count($result) > 0) {
    echo '{"reference": "' . $result[0] . '", "success":"true"}';
} else {
    // TODO: Whatever....
}
?>  
</body>
</html>

答案 1 :(得分:0)

感谢J0e3gan的回答!工作完美。我还发现这种替代方案效果很好。基本上创建一个新的DOM,然后抓住标签内部的内容。

$doc = new DOMDocument('1.0', 'utf-8');
$doc->loadXML( $soapResponse );
$XMLresults     = $doc->getElementsByTagName("SearchFlightAvailability33Response");
$output = $XMLresults->item(0)->nodeValue;

礼貌: How to convert SOAP response to PHP Array?