I have a SOAP response as follows:
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope" xmlns="">
<faultcode>stuff</faultcode>
<faultstring>stuff</faultstring>
<detail>
<ns2:Exception xmlns:ns2="http://blah.com/">
<message>stuff</message>
</ns2:Exception>
</detail>
</S:Fault>
</S:Body>
</S:Envelope>
I need to extract faultcode, faultstring, and message.
I have tried SimpleXML_load_string, SimpleXMLElement, DOMDocument, registerXPathNamespace and json_decode but can't seem to get the exact procedure correct because I get errors instead of results. Thanks in advance.
Latest attempt:
$xmle1 = SimpleXML_load_string(curl_exec($ch));
if (curl_errno($ch)) {
print "curl error: [" . curl_error($ch) . "]";
} else {
$xmle1->registerXPathNamespace('thing1', 'http://blah.com/');
foreach ($xml->xpath('//thing1:message') as $item) {
echo (string) $item;
}
<?php
$string = <<<XML
<?xml version="1.0" ?>
<S:Envelope
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<S:Fault
xmlns:ns4="http://www.w3.org/2003/05/soap-envelope"
xmlns="">
<faultcode>stuff</faultcode>
<faultstring>stuff</faultstring>
<detail>
<ns2:Exception
xmlns:ns2="http://blah.com/">
<message>stuff</message>
</ns2:Exception>
</detail>
</S:Fault>
</S:Body>
</S:Envelope>
XML;
$_DomObject = new DOMDocument;
$_DomObject->loadXML($string);
if (!$_DomObject) {
echo 'Error while parsing the document';
exit;
}
$s = simplexml_import_dom($_DomObject);
foreach(['faultcode','faultstring','message'] as $tag){
echo $tag.' => '.$_DomObject->getElementsByTagName($tag)[0]->textContent.'<br/>';
}
?>
outputs
faultcode => stuff
faultstring => stuff
message => stuff
you might want to write a class to parse the XML string and build an nice Fault object with methods for easier access after you parse it.
Related
I'm getting an XML response that I cannot parse. Here's the thing:
<?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>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Exception occurred</faultstring>
<faultactor>https://services.lso.com/partnershippingservices/v1_5/PricingService.asmx</faultactor>
<detail>
<webServiceException xmlns="https://services.lso.com/WebServiceException/v1">
<code>600121</code>
<action>To zip code is outside of service area.</action>
</webServiceException>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
It's the response when an error occurs. What I want to get is the values of both code and action.
I know how to handle the response when the request was correctly processed, but I can't do much when an error is returned.
Just to give you an idea, this is what I'm doing with the response I can handle:
$responseRate = simplexml_load_string($xmlRateResponse);
$getTotalCharge = $responseRate->children('http://schemas.xmlsoap.org/soap/envelope/')
->Body->children()
->EstimatePriceResponse;
$totalCharge = (float)$getTotalCharge->EstimatePriceResult->TotalCharge;
echo $totalCharge;
With this, I can display the rate that is returned.
Any help will be appreciated. Thanks.
Alright, here's a solution.
$xmlResponse = new SimpleXMLElement($errorResponse);
$xmlResponse->registerXPathNamespace('soap','http://schemas.xmlsoap.org/soap/envelope/');
$result=$xmlResponse->xpath('//soap:Fault');
foreach ($result as $body) {
echo $body->detail->webServiceException->code . "<br>";
echo $body->detail->webServiceException->action . "<br>";
}
This is going to return "600121" and "To zip code is outside of service area.", which is what I want.
I have been trying to parse an XML SOAP response in PHP but I continue to get errors. I cannot figure out why these errors are occuring.
Response from the server, stored in $response as a string (with sensitive data removed):
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:ServerVersionInfo MajorVersion="15" MinorVersion="20" MajorBuildNumber="323" MinorBuildNumber="19" Version="V2017_10_09" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</s:Header>
<s:Body>
<m:GetAttachmentResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:GetAttachmentResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Attachments>
<t:FileAttachment>
<t:AttachmentId Id="id number"/>
<t:Name>message-footer.txt</t:Name>
<t:ContentType>text/plain</t:ContentType>
<t:ContentId>contentid.prod.outlook.com</t:ContentId>
<t:Content>file contents</t:Content>
</t:FileAttachment>
</m:Attachments>
</m:GetAttachmentResponseMessage>
</m:ResponseMessages>
</m:GetAttachmentResponse>
</s:Body>
</s:Envelope>
My code:
$data = simplexml_load_string($response);
$fileData = $data
->children('s:', true)->Body
->children('m:', true)->GetAttachmentResponse->ResponseMessages->GetAttachmentResponseMessage->Attachments
->children('t:', true)->FileAttachment;
I need to be able to get the file name, content type, and content. I continue to get the following error: Node no longer exists (on line 4 here).
For reference, I have been following this guide: https://joshtronic.com/2014/07/13/parsing-soap-responses-with-simplexml/
Any help is greatly appreciated.
I don't know how to read such a complex XML file with simplexml, but I know that DOMDocument works very well for it.
<?php
$source = file_get_contents('file.xml');
$dom = new DOMDocument("1.0", "UTF-8");
$dom->preserveWhiteSpace = false;
$dom->loadXml($source);
$xpath = new DOMXPath($dom);
$xpath->registerNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");
$xpath->registerNamespace("m", "http://schemas.microsoft.com/exchange/services/2006/messages");
$xpath->registerNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
$xpath->registerNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
$xpath->registerNamespace("t", "http://schemas.microsoft.com/exchange/services/2006/types");
$fileAttachments = $xpath->query('//m:GetAttachmentResponseMessage/m:Attachments/t:FileAttachment');
/* #var DOMElement $fileAttachment */
foreach ($fileAttachments as $fileAttachment) {
echo 'Name: ' . $xpath->query('t:Name', $fileAttachment)->item(0)->nodeValue . "\n";
echo 'ContentType: ' . $xpath->query('t:ContentType', $fileAttachment)->item(0)->nodeValue . "\n";
echo 'Content: ' . $xpath->query('t:Content', $fileAttachment)->item(0)->nodeValue . "\n";
}
Not too sure what I'm doing wrong with parsing/reading an xml document.
My guess is that it's not standardized, and I'm going to need a different process to read anything from the string.
If that's the case, then I'm rather excited to learn how someone would read the xml.
Here's what I've got, and what I'm doing.
example.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="someurl.php"?>
<response>
<status>Error</status>
<error>The error message I need to extract, if the status says Error</error>
</response>
read_xml.php
<?php
$content = 'example.xml';
$string = file_get_contents($content);
$xml = simplexml_load_string($string);
print_r($xml);
?>
I'm getting no result back from the print_r.
I switched the xml to something more standard, like:
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
...and it worked fine. So I'm sure it's due to a non-standard format, passed back from the source I'm getting it from.
How would I extract the <status> and <error> tags?
Tek has a good answer, but if you want to use SimpleXML, you can try something like this:
<?php
$xml = simplexml_load_file('example.xml');
echo $xml->asXML(); // this will print the whole string
echo $xml->status; // print status
echo $xml->error; // print error
?>
EDIT: If you have multiple <status> and <error> tags in your XML, have a look at this:
$xml = simplexml_load_file('example.xml');
foreach($xml->status as $status){
echo $status;
}
foreach($xml->error as $error){
echo $error;
}
I'm assuming <response> is your root. If it isn't, try $xml->response->status and $xml->response->error.
I prefer to use PHP's DOMDocument class better.
Try something like this:
<?php
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="someurl.php"?>
<response>
<status>Error</status>
<error>The error message I need to extract, if the status says Error</error>
</response>';
$dom = new DOMDocument();
$dom->loadXML($xml);
$statuses = $dom->getElementsByTagName('status');
foreach ($statuses as $status) {
echo "The status tag says: " . $status->nodeValue, PHP_EOL;
}
?>
Demo: http://codepad.viper-7.com/mID6Hp
I created a SOAP client in PHP:
$client = new SoapClient("http://xxxx.net/Service/Service.svc?wsdl");
$response= $client->GetHotelNugget($data);
But I can't parse the response. I need <a:TITLE> tag value.
Output of the SOAP client:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetHotelNuggetResponse xmlns="http://tempuri.org/">
<GetHotelNuggetResult xmlns:a="http://schemas.datacontract.org/2004/07/Model" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:HotelNugget>
<a:NUGGETNAME>Yaz Tatili Otelleri</a:NUGGETNAME>
<a:NUGGETORDER>10</a:NUGGETORDER>
<a:PARENTUNIQUECODE>AS_SOL_UST</a:PARENTUNIQUECODE>
<a:REWRITENUGGETNAME>yaz-tatili-otelleri</a:REWRITENUGGETNAME>
<a:TITLE>Yaz Tatili Otelleri</a:TITLE>
<a:UNIQUECODE>YTOTL</a:UNIQUECODE>
<a:WEBNUGGETID>306</a:WEBNUGGETID>
</a:HotelNugget>
<a:HotelNugget>
<a:NUGGETNAME>Ramazan Fırsatları</a:NUGGETNAME>
<a:NUGGETORDER>20</a:NUGGETORDER>
<a:PARENTUNIQUECODE>AS_SOL_UST</a:PARENTUNIQUECODE>
<a:REWRITENUGGETNAME>ramazan-firsatlari</a:REWRITENUGGETNAME>
<a:TITLE>Ramazan Fırsatları</a:TITLE>
<a:UNIQUECODE>RFIR</a:UNIQUECODE>
<a:WEBNUGGETID>308</a:WEBNUGGETID>
</a:HotelNugget>
<a:HotelNugget>
<a:NUGGETNAME>Ramazan Bayramı Otelleri</a:NUGGETNAME>
<a:NUGGETORDER>30</a:NUGGETORDER>
<a:PARENTUNIQUECODE>AS_SOL_UST</a:PARENTUNIQUECODE>
<a:REWRITENUGGETNAME>ramazan-bayrami-otelleri</a:REWRITENUGGETNAME>
<a:TITLE>Ramazan Bayramı Otelleri</a:TITLE>
<a:UNIQUECODE>RBO</a:UNIQUECODE>
<a:WEBNUGGETID>283</a:WEBNUGGETID>
</a:HotelNugget>
</GetHotelNuggetResult>
</GetHotelNuggetResponse>
</s:Body>
</s:Envelope>
Try below code and check the print_r value
$xmlResp = simplexml_load_string($response);
$jsonResp = json_encode($xmlResp);
$arrResp = json_decode($jsonResp);
foreach($arrResp as $k=>$v) {
print_r($v);
}
You can then access the TITLE tag inside foreach by something like below
$v['HotelNugget']['TITLE'];
I'm using cURL to POST a SOAP request. The response is as follows:
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:To>http://www.w3.org/2005/08/addressing/anonymous</wsa:To>
<wsa:Action>http://www.csapi.org/schema/parlayx/common/v3_1/TerminalLocationPort/getLocationForGroupResponse</wsa:Action>
</env:Header>
<env:Body>
<ns2:getLocationForGroupResponse xmlns:ns2="http://www.csapi.org/schema/parlayx/terminal_location/v3_1/local">
<ns2:result>
<address>234983</address>
<reportStatus>Retrieved</reportStatus>
<currentLocation>
<latitude>12.5665</latitude>
<longitude>43.7708</longitude>
<timestamp>2012-01-03T17:06:16.805+01:30</timestamp>
</currentLocation>
</ns2:result>
<ns2:result>
<address>423903</address>
<reportStatus>Retrieved</reportStatus>
<currentLocation>
<latitude>12.2165</latitude>
<longitude>43.6518</longitude>
<timestamp>2012-01-03T17:06:16.824+01:30</timestamp>
</currentLocation>
</ns2:result>
</ns2:getLocationForGroupResponse>
</env:Body>
</env:Envelope>
I use this to decode:
$err = curl_error($soap_do);
$result = curl_exec($soap_do);
$xml = simplexml_load_string($result);
$ns = $xml->getNamespaces(true);
$soap = $xml->children($ns['env']);
$getaddressresponse = $soap->body->children($ns['ns2']);
foreach ($getaddressresponse->children() as $item) {
echo (string) $item->address . '<br />';
}
I'm having trouble decoding this with SimpleXML. This link seems most relevant to my situation but I'm unable to apply it to my case as the simpleXML element just
Warning: SimpleXMLElement::children() [simplexmlelement.children]: Node no longer exists in C:\.php on line 33 /*(line with the for each statement)*/
Any suggestions?
UPDATE:
If the server responds with the following error, how would I detect it..?
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:To>http://www.w3.org/2005/08/addressing/anonymous</wsa:To>
<wsa:Action>http://www.w3.org/2005/08/addressing/fault</wsa:Action>
</env:Header>
<env:Body>
<env:Fault>
<faultcode>env:Server</faultcode>
<faultstring>Service Exception</faultstring>
<detail>
<ns1:ServiceException xmlns:ns1="http://www.csapi.org/schema/parlayx/common/v3_1" xmlns:ns2="http://www.csapi.org/schema/parlayx/terminal_location/v3_1/local">
<messageId>SVC004</messageId>
<text>Trip not Found for this MSISDN</text>
</ns1:ServiceException>
</detail>
</env:Fault>
</env:Body>
</env:Envelope>
Variable and property names are case sensitive and while I was testing it, it turned out there's other stuff as well. The following works:
$soap = $xml->children($ns['env']);
$getaddressresponse = $soap->Body->children($ns['ns2']);
foreach ($getaddressresponse->getLocationForGroupResponse->children($ns['ns2']) as $item)
{
$item = $item->children();
echo $item->address . '<br />';
}
To answer the updated question:
$fault = $soap->Body->children($ns['env']);
if (isset($fault->Fault))
{
// Handle error
}