Question

I'm making a SOAP call through php to an external webservice. I finally have it working. The last step is just parsing the response from the SOAP service.

When I do :

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

I expect to get and I see as the HTML webpage response:

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

However when I look in developer tools source/preview I see this:

{"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"} 

Pretty much the variable I need is in the middle of a ton of XML stuff! How can I just pull out the needed variable, and return it as a json?

In case it helps, here's my code:

$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>";

This all seems to work, I get the following output in the html/php page:

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

The __last_response is the code I need. I'm trying to send it as a JSON.

When I look at the developer tools at the preview/source of the page I get this:

 <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> 
Was it helpful?

Solution

Use the SimpleXMLElement::xpath method with the following path...

/soap:Envelope/soap:Body/a:GetPaynetReferenceResponse/a:GetPaynetReferenceResult/a:PaynetReference/text()

after registering the following namespace prefixes with 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/

Taking this approach, transform...

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

...as follows:

$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....
}

EDIT:

To be perfectly clear about exactly how I checked this solution, here is the PoC I sketched without being able to use $client->__getLastResponse() per se:

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

OTHER TIPS

Thanks J0e3gan for the answer! Worked perfect. I also found that this alternative works well. Basically create a new DOM, and just grab whats inside the tags.

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

Courtesy of: How to convert SOAP response to PHP Array?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top