Parsing JSON inside XML response php - php

<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:getRatesResponse xmlns:ns1="urn:rpxwsdl">
<return xsi:type="xsd:string">{"RPX":{"TITLE":"Rates From Jakarta (JAK) TO Denpasar (DPS), Weight 1 Kg","DATA":[{"SERVICE":"PAS Reguler (PSR)","FREIGHT_CHARGE":"27723","TOT_CHARGE":"27723","PRICE":"27723","DISCOUNT":"0","ETF":"N\/A","ETD":"N\/A"},{"SERVICE":"","FREIGHT_CHARGE":"0","TOT_CHARGE":"0","PRICE":"0","DISCOUNT":"0","ETF":"0","ETD":"0"}]}}</return>
</ns1:getRatesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I have a json inside an xml response. however how do i retrieve it from the response.

Use the DOM classes to get the relevant text content. This will handle the entities. Then you can simply use json_decode.
For example (demo):
<?php
declare(strict_types=1);
$xml = <<<XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:getRatesResponse xmlns:ns1="urn:rpxwsdl">
<return xsi:type="xsd:string">{"RPX":{"TITLE":"Rates From Jakarta (JAK) TO Denpasar (DPS), Weight 1 Kg","DATA":[{"SERVICE":"PAS Reguler (PSR)","FREIGHT_CHARGE":"27723","TOT_CHARGE":"27723","PRICE":"27723","DISCOUNT":"0","ETF":"N\/A","ETD":"N\/A"},{"SERVICE":"","FREIGHT_CHARGE":"0","TOT_CHARGE":"0","PRICE":"0","DISCOUNT":"0","ETF":"0","ETD":"0"}]}}</return>
</ns1:getRatesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
XML;
$doc = new DOMDocument('1.0', 'ISO-8859-1');
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
$xpath->registerNamespace('ns1', 'urn:rpxwsdl');
$item = $xpath->query('/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getRatesResponse/return');
if ($item->length > 0) {
print_r(
json_decode($item->item(0)->textContent, true, 512, JSON_THROW_ON_ERROR)
);
}

Related

How filter through XML response from CURL HTTP POST Request

Response from CURL request:
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:header>
<soap-env:body>
<ipgapi:ipgapiorderresponse xmlns:ipgapi="http://ipg-online.com/ipgapi/schemas/ipgapi" xmlns:a1="http://ipg-online.com/ipgapi/schemas/a1" xmlns:v1="http://ipg-online.com/ipgapi/schemas/v1">
<ipgapi:approvalcode>Y:761862:4515799310:PPXP:0037</ipgapi:approvalcode>
<ipgapi:avsresponse>PPX</ipgapi:avsresponse>
<ipgapi:brand>VISA</ipgapi:brand>
<ipgapi:country>GBR</ipgapi:country>
<ipgapi:commercialserviceprovider>BOSMS</ipgapi:commercialserviceprovider>
<ipgapi:orderid>A-966025d3-81a2-453a-820e-bb145e8390d1</ipgapi:orderid>
<ipgapi:ipgtransactionid>84515799310</ipgapi:ipgtransactionid>
<ipgapi:paymenttype>CREDITCARD</ipgapi:paymenttype>
<ipgapi:processorapprovalcode>761862</ipgapi:processorapprovalcode>
<ipgapi:processorccvresponse>P</ipgapi:processorccvresponse>
<ipgapi:processorreferencenumber>761862</ipgapi:processorreferencenumber>
<ipgapi:processorresponsecode>00</ipgapi:processorresponsecode>
<ipgapi:processorresponsemessage>AUTH CODE:761862</ipgapi:processorresponsemessage>
<ipgapi:tdate>1521047872</ipgapi:tdate>
<ipgapi:tdateformatted>2018.03.14 18:17:52 (CET)</ipgapi:tdateformatted>
<ipgapi:terminalid>21400371</ipgapi:terminalid>
<ipgapi:transactionresult>APPROVED</ipgapi:transactionresult>
<ipgapi:transactiontime>1521047872</ipgapi:transactiontime>
</ipgapi:ipgapiorderresponse>
</soap-env:body>
</soap-env:header>
</soap-env:envelope>
I've tried the following:
$responseXML = '<?xml version="1.0" encoding="UTF-8"?>
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:header>
<soap-env:body>
<ipgapi:ipgapiorderresponse xmlns:ipgapi="http://ipg-online.com/ipgapi/schemas/ipgapi" xmlns:a1="http://ipg-online.com/ipgapi/schemas/a1" xmlns:v1="http://ipg-online.com/ipgapi/schemas/v1">
<ipgapi:approvalcode>Y:761862:4515799310:PPXP:0037</ipgapi:approvalcode>
<ipgapi:avsresponse>PPX</ipgapi:avsresponse>
<ipgapi:brand>VISA</ipgapi:brand>
<ipgapi:country>GBR</ipgapi:country>
<ipgapi:commercialserviceprovider>BOSMS</ipgapi:commercialserviceprovider>
<ipgapi:orderid>A-966025d3-81a2-453a-820e-bb145e8390d1</ipgapi:orderid>
<ipgapi:ipgtransactionid>84515799310</ipgapi:ipgtransactionid>
<ipgapi:paymenttype>CREDITCARD</ipgapi:paymenttype>
<ipgapi:processorapprovalcode>761862</ipgapi:processorapprovalcode>
<ipgapi:processorccvresponse>P</ipgapi:processorccvresponse>
<ipgapi:processorreferencenumber>761862</ipgapi:processorreferencenumber>
<ipgapi:processorresponsecode>00</ipgapi:processorresponsecode>
<ipgapi:processorresponsemessage>AUTH CODE:761862</ipgapi:processorresponsemessage>
<ipgapi:tdate>1521047872</ipgapi:tdate>
<ipgapi:tdateformatted>2018.03.14 18:17:52 (CET)</ipgapi:tdateformatted>
<ipgapi:terminalid>21400371</ipgapi:terminalid>
<ipgapi:transactionresult>APPROVED</ipgapi:transactionresult>
<ipgapi:transactiontime>1521047872</ipgapi:transactiontime>
</ipgapi:ipgapiorderresponse>
</soap-env:body>
</soap-env:header>
</soap-env:envelope>';
$xml = simplexml_load_string($responseXML);
print_r($xml);
// Returns empty object
I've also tried the following:
$xml = new SimpleXMLElement($responseXML);
print_r($xml);
// This also returns empty object
Could someone help me figure out what's going wrong with this?
Using print_r(); with a SimpleXMLElement usually doesn't give anything useful. Instead you should use asXML() which outputs the original XML.
$xml = simplexml_load_string($responseXML);
echo $xml->asXML();
Which gives
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:header>
<soap-env:body>
...
You can access the data by using something like...
$xml = simplexml_load_string($responseXML);
$body = $xml->xpath("//soap-env:body");
$bodyData = $body[0]->children("ipgapi", true);
echo $bodyData->ipgapiorderresponse->approvalcode;
So $bodyData is the <ipgapi:ipgapiorderresponse ...> element and so accessing each part of that is by using the last line. You can use the element name (minus the namespace prefix ipgapi as this is taken care of with the children() call earlier). That line outputs
Y:761862:4515799310:PPXP:0037

How to parse my SOAP XML response in PHP?

This is my SOAP response:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://localhost:8000/soap/index.php?wsdl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:testMethodResponse>
<return xsi:type="xsd:boolean">true</return>
</ns1:testMethodResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I'd like to return the true. How can I do this?
This is what I'm trying:
$xml = simplexml_load_string($res, NULL, NULL, "http://schemas.xmlsoap.org/soap/envelope/");
$ns = $xml->getNamespaces(true);
$soap = $xml->children($ns['SOAP-ENV']);
$res = $soap->Body->children($ns['ns1']);
foreach ($res->TestMethodResponse as $item) {
echo $item->result.PHP_EOL;
}

Remove automatically applied namespace in php's SimpleXML

I am trying to create a SOAP request for a paypal express checkout with SimpleXML. However, I am experiencing a behaviour I don't yet understand.
The envelope and its header are generated this way:
$envelope = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:ebay:apis:eBLBaseComponents"
xmlns:ns2="urn:ebay:api:PayPalAPI"
/>
');
$header = $envelope->addChild('SOAP-ENV:Header');
$requesterCredentials = $header->addChild('ns2:RequesterCredentials');
$credentials = $requesterCredentials->addChild('ns1:Credentials');
$credentials->addChild('ns1:Username', 'foo');
$credentials->addChild('ns1:Password', 'bar');
Which yields the following output:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:ebay:apis:eBLBaseComponents"
xmlns:ns2="urn:ebay:api:PayPalAPI">
<SOAP-ENV:Header>
<SOAP-ENV:RequesterCredentials>
<SOAP-ENV:Credentials>
<SOAP-ENV:Username>foo</SOAP-ENV:Username>
<SOAP-ENV:Password>bar</SOAP-ENV:Password>
</SOAP-ENV:Credentials>
</SOAP-ENV:RequesterCredentials>
</SOAP-ENV:Header>
</SOAP-ENV:Envelope>
Every node is now prefixed with SOAP-ENV, which is not what I want. Only the root node and header should be prefixed with SOAP-ENV, the other tags should get the defined namespace prepended in addChild().
The desired output should be:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:ebay:apis:eBLBaseComponents"
xmlns:ns2="urn:ebay:api:PayPalAPI">
<SOAP-ENV:Header>
<ns2:RequesterCredentials>
<ns1:Credentials>
<ns1:Username>foo</ns1:Username>
<ns1:Password>bar</ns1:Password>
</ns1:Credentials>
</ns2:RequesterCredentials>
</SOAP-ENV:Header>
</SOAP-ENV:Envelope>
What am I doing wrong here?
addChild takes the namespace as the third parameter:
$requesterCredentials = $header->addChild('RequesterCredentials', null, 'urn:ebay:api:PayPalAPI');
$credentials = $requesterCredentials->addChild('Credentials', null, 'urn:ebay:apis:eBLBaseComponents');
$credentials->addChild('Username', 'foo', 'urn:ebay:apis:eBLBaseComponents');
$credentials->addChild('Password', 'bar', 'urn:ebay:apis:eBLBaseComponents');

php SoapClient - make a call with multiple root tags in request

Here's the xml structure that I want to achieve:
<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:method>
<auth>
...
</auth>
<data>
...
</data>
</ns1:method>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
</XML>
My code:
<?php
$client = new SoapClient(null, array('location' => "http://www.test.com/soap.php",
'uri' => "http://tempuri.org/",
'trace' => true,'exceptions' => true,'cache_wsdl' => WSDL_CACHE_NONE));
$request = new stdClass();
$request->auth = new stdClass();
$request->data = new stdClass();
$client->__soapCall("method", array($request));
Please note: SoapClient doesn't allow me to insert anything other than array in second param to the __soapCall method.
So here's what I'm getting:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:method>
<param0 xsi:type="SOAP-ENC:Struct">
<auth xsi:type="SOAP-ENC:Struct"/>
<data xsi:type="SOAP-ENC:Struct"/>
</param0>
</ns1:method>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
As you can see, php added a root tag for my request - param0. Is there a way I can escape this? I need to have 2 "root" elements in that request parameter. How can I achieve that?
did you try this way : $client->__soapCall("method", $request);?
Thanks all for answering. I solved the issue with the help of SoapParam:
$client->__soapCall("method", array(
new SoapParam($request->auth, "auth"),
new SoapParam($request->data, "data"),
));

Parsing XML request

I'm very very new to being on the Server side of things. I need to set up a simple server.php to receive xml requests.
I'm not even sure how to start with this. I am used to the normal Post/Get variables from forms.
Here's an example of what I'm listening for, and needing to respond to:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<authenticate xmlns="http://someplace.someplace.com/">
<strUserName xsi:type="xsd:string">username</strUserName>
<strPassword xsi:type="xsd:string">password</strPassword>
</authenticate>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Obviously there's a username/password I can see inside.
Validating the user/pass is the easy part, but how do I parse that out?
You can also use DOM element to access your desired values:
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<authenticate xmlns="http://someplace.someplace.com/">
<strUserName xsi:type="xsd:string">username</strUserName>
<strPassword xsi:type="xsd:string">password</strPassword>
</authenticate>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>';
$dom = new DOMDocument();
$dom->loadXML( $xml );
$username = $dom->getElementsByTagName('strUserName')->item(0)->nodeValue;
$password = $dom->getElementsByTagName('strPassword')->item(0)->nodeValue;
Give it a try with SimpleXML, you have a few examples here:
SimpleXML examples
You should probably use existing API when parsing a SOAP request. This will not only automatically get rid of your parsing problems but also generate correct SOAP output.
Example:
$request = '<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<authenticate xmlns="http://someplace.someplace.com/">
<strUserName xsi:type="xsd:string">foo</strUserName>
<strPassword xsi:type="xsd:string">bar</strPassword>
</authenticate>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>';
$s = new SoapServer(NULL, array('uri' => 'http://someplace.someplace.com/'));
$s->setClass("Auth");
$s->handle($request);
class Auth
{
public function authenticate($strUserName, $strPassword)
{
return "U: $strUserName; P: $strPassword";
}
}
Note: If you do not pass an argument to handle() it will use POST data.

Categories