Parsing an XML response with namespaces - php

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.

Related

soap xml response - how to get that stubborn data out [duplicate]

This question already has answers here:
Reference - How do I handle Namespaces (Tags and Attributes with a Colon in their Name) in SimpleXML?
(2 answers)
Closed 3 years ago.
I'm trying to get the contents of the faultstring element and I'm more comfortable with SimpleXML's object syntax ($xml->...->faultstring.) The DomDocument method below works, but I'd prefer to stick with SimpleXML.
PHP version 5.6.40, Libxml 2.9.1.
$xmlResponse = '<?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>Server did not recognize the value of HTTP Header SOAPAction: https://gw1.domain.com:4430/.</faultstring>
<detail />
</soap:Fault>
</soap:Body>
</soap:Envelope>';
// DOES NOT WORK
$xml = simplexml_load_string($xmlResponse,NULL,NULL,"http://schemas.xmlsoap.org/soap/envelope/");
$faultstring = (string) ($xml->Body->Fault->faultstring);
var_dump($faultstring);
// WORKS
$_DomObject = new DOMDocument;
$_DomObject->loadXML($xmlResponse);
if (!$_DomObject) die("Error while parsing the document");
$s = simplexml_import_dom($_DomObject);
foreach(['faultcode','faultstring','detail'] as $tag) {
echo $tag.' => '.$_DomObject->getElementsByTagName($tag)[0]->textContent.'<br/>';
}
<?php
$xmlResponse = <<<XML
<?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>Server did not recognize the value of HTTP Header SOAPAction: https://gw1.domain.com:4430/.</faultstring>
<detail />
</soap:Fault>
</soap:Body>
</soap:Envelope>
XML;
XML namespaces are getting in the way; they're the soap: prefix on the element names. It's possible to register all the namespaces and get it working that way, but just using XPath is easier:
$xml = new SimpleXMLElement($xmlResponse);
$fault = $xml->xpath("//faultstring");
echo (string)$fault[0] . "\n";
And here's how it looks using namespaces. You still get the object syntax, but it becomes a lot more complicated.
$xml = new SimpleXMLElement($xmlResponse);
$fault = $xml->children("soap", true)->Body->children("soap", true)->Fault->children()->faultstring;
echo (string)$fault . "\n";
Output for both:
Server did not recognize the value of HTTP Header SOAPAction: https://gw1.domain.com:4430/.

XML interpretation issue

I am working using soap, when the soap response is sent back all the < and > are represented using special characters.
<?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">
<UploadFileNew_XMLResponse xmlns="http://tempuri.org/GAPS_Uploader/FileUploader">
<UploadFileNew_XMLResult>
<?xml version="1.0" encoding="utf-8"?><Response><ResCode>1009</ResCode><Message>3 transaction(s) failed</Message><Errors><Error><Rownum>1</Rownum><Description>: Reference already exist </Description><Res_Code>59b1ebbc1c012 </Res_Code></Error><Error><Rownum>2</Rownum><Description>: Reference already exist </Description><Res_Code>59cb93d6c1d30 </Res_Code></Error><Error><Rownum>3</Rownum><Description>: Reference already exist </Description><Res_Code>59cbaca456589 </Res_Code></Error></Errors></Response>
</UploadFileNew_XMLResult>
</UploadFileNew_XMLResponse>
</soap:Envelope>
please how can i simplexml_load_string to process this result.
$response = htmlspecialchars_decode($response);
$parser = simplexml_load_string($response);
print_r($parser);
Change the order:
$parser = simplexml_load_string($response);
$response = htmlspecialchars_decode($parser->UploadFileNew_XMLResponse->UploadFileNew_XMLResult);
print_r($response);

PHP : XML Parsing Error - simplexml_load_string() expects parameter 1 to be string

I am trying to parse the XML response of a method in PHP.Below is my response.
Response:
<FindIssuesResponse xmlns="http://Service/">
<FindIssuesResult>
<FindIssues xmlns="">
<GetIssue>
</GetIssue>
<GetIssue>
<IssuesIssueNbr>1226</IssuesIssueNbr>
<IssuesIssueDescription>Issue Descreption</IssuesIssueDescription>
<IssuesIssueSolution>Duplicate ticket for Issue #1223</IssuesIssueSolution>
<IssuesIssueTypeID>7</IssuesIssueTypeID>
<IssueNotes>
<NotesIssueNbr>1226</NotesIssueNbr>
<NotesNoteID>16344</NotesNoteID>
<NotesNoteCreatedDate>2013-10-23T01:28:50.383-04:00</NotesNoteCreatedDate>
<NotesNoteText>text</NotesNoteText>
<NotesNotePrivate>false</NotesNotePrivate>
<NotesFirstNote>true</NotesFirstNote>
<NotesDatabaseID>IssueTrak</NotesDatabaseID>
<NotesCreatedBy>user#example.com</NotesCreatedBy>
<NotesNoteTime>0</NotesNoteTime>
<NotesIsRichText>true</NotesIsRichText>
</IssueNotes>
</GetIssue>
<GetIssue>
</GetIssue>
<GetIssue>
</GetIssue>
Please help me to parse this XML to get the first tag value "NotesIssueNbr"
I have written like this.
Code:
<?php
require_once 'nusoap.php';
$wsdl="D:\PHP\ITAlert.wsdl";
$client=new SoapClient($wsdl);
$searchCriteria='<FindIssues><ReturnSchema>N</ReturnSchema><IssueStatus>Open</IssueStatus><IssuesNextActionBy><UsersUserID>user#example.com</UsersUserID></IssuesNextActionBy></FindIssues>';
$params=array('searchCriteria'=>$searchCriteria,'username'=>'user#example.com','password'=>'password');
$response = $client->__soapCall('FindIssues', array($params));
$issues = simplexml_load_string($response->FindIssuesResult);
$value1=$issues->issues->FindIssues->GetIssue->IssuesIssueNbr;
echo $value1;
?>
May I know the way to parse this format
<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>
<FindIssuesResponse xmlns="http://IssueTrakService/">
<FindIssuesResult>
<FindIssues xmlns="">
<GetIssue>
<IssuesIssueNbr>1223</IssuesIssueNbr>

SOAP response - parsing xml in php, how to access?

I have response from webservice:
<?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:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:H1 xsi:type="ns1:H1">
<BOGUS>
<time>1411967345</time>
<status>1</status>
<speed>0</speed>
</BOGUS>
<BOGUS>
<time>1411964888</time>
<status>10</status>
<speed>0</speed>
</BOGUS>
</ns1:H1>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
How can I access to element time or status in BOGUS[0] or BOGUS[1]?
I tried this:
$soap = simplexml_load_string($str);
$response = $soap->children('http://schemas.xmlsoap.org/soap/envelope/')->Body->children('http://tempuri.org/')->H1;
$time = $response->BOGUS[1]->time;
echo $time;
, but it's not working. Returns: Notice: Trying to get property of non-object
tempuri.org is right. I pasted xml response on: xmlgrid.net and got correct tree.
I'd recommandate to use Zend Soap Client for PHP. There u can do like this:
$client = new Zend_Soap_Client("MyService.wsdl");
$result = $client->yourMethod(<YouParameters ...>);
echo $result->H1->BOGUS[1]->time;
See:
http://framework.zend.com/manual/1.12/de/zend.soap.client.html
You can do it by loops as you are getting array in return
foreach ($response as $res)
{
$time = $res->BOGUS[1]->time;
echo $time;
}

Sending XML string (not array) from PHP SOAP or nusoap to .NET service

I'm new to SOAP and I'm having issues (yes, I have searched - extensively, but I can't seem to match my very simple requirement - sending a single XML string) with sending some output to a .NET server to match this:
POST /someurl.asmx HTTP/1.1
Host: www.somehost.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://somehost.com/SubmitCalls"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<SubmitCalls xmlns="http://somehost/">
<request>string</request>
</SubmitCalls>
</soap:Body>
</soap:Envelope>
My nusoap code looks like this:
<?php
require_once('../lib/nusoap.php');
$bodyxml = '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<SubmitCalls xmlns="http://somehost/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<request>
<?xml version="1.0" encoding="UTF-8"?>
<bXML xmlns="http://somehost/Schemas" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<From>
<UserName>some username</UserName>
<Password>some password</Password>
</From>
<Calls>
<Call>
<Reference>11111</Reference>
<Name>Joe Bloggs</Name>
<Tel1>02075574200</Tel1>
<Tel2>02075574201</Tel2>
<Tel3>02075574202</Tel3>
<Tel4>02075574203</Tel4>
<Tel5>02075574204</Tel5>
<CLI>08448220640</CLI>
<CallTime>09:00</CallTime>
<FileName>02075574200_1</FileName>
</Call>
<Call>
<Reference>11111</Reference>
<Name>Joe Bloggs</Name>
<Tel1>02075574200</Tel1>
<Tel2>02075574206</Tel2>
<Tel3>02075574207</Tel3>
<Tel4>02075574208</Tel4>
<Tel5>02075574209</Tel5>
<CLI>08448220640</CLI>
<CallTime>09:00</CallTime>
<FileName>02075574200_2</FileName>
</Call>
</Calls>
</bXML>
</request>
</SubmitCalls>
</soap:Body>
</soap:Envelope>
';
$client = new nusoap_client("somehost?WSDL",true);
$err = $client->getError();
if ($err) {
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
exit();
}
$client->soap_defencoding = 'utf-8';
$client->useHTTPPersistentConnection();
$client->setUseCurl($useCURL);
$bsoapaction = "http://somehost/SubmitCalls";
$result = $client->send($bodyxml, $bsoapaction);
// Check for a fault
if ($client->fault) {
echo '<h2>Fault</h2><pre>';
print_r($result);
echo '</pre>';
} else {
// Check for errors
$err = $client->getError();
if ($err) {
// Display the error
echo '<h2>Error</h2><pre>' . $err . '</pre>';
} else {
// Display the result
echo '<h2>Result</h2><pre>';
print_r($result);
echo '</pre>';
}
}
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
echo '<h2>Client Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
echo '<h2>Proxy Debug</h2><pre>' . htmlspecialchars($proxy->debug_str, ENT_QUOTES) . '</pre>';
?>
(Obiously, all the somehost and usernames are correct in the final script). I can connect to the WSDL, read it, there's only one method I'm interested in (SubmitCalls) which only has one part, named 'parameters' in the WSDL schema. The above throws a 400 Bad request error - any ideas where I'm going wrong?
I've tried using PHP SOAP instead, but I simply can't seem to send an XML string as the body of the SOAP request. I've been fiddling with this for the best part of three days and read a zillion web pages, but I still can't get it right. Please help.... if you could show me how to do this using either library I would be enormously grateful....
You can send plain XML with the $client->send() method.
$raw_xml = "<Your_XML>...</Your_XML>";
$msg = $client->serializeEnvelope("$raw_xml");
$result=$client->send($msg, $endpoint);
You can see the example here:
http://itworkarounds.blogspot.com/2011/07/send-raw-xml-with-php-nusoap.html
If that does't work you can try posting the XML with CURL.
-try this-
$xml = simplexml_load_string('<data>x</data>')
and then (nusoap)
$result = $client->call('host', array('parameter' =>$xml)
Not exactly an answer to the issue - but it is now solved. The service provider created a new method, which was identical in all respects except that it allowed for an XML document rather than a string. By making some minor alterations to the contents of the $bodyxml variable, and sending to this new method, it appears to work fine.
By the way - anyone looking to debug SOAP applications should really look at grabbing SOAP UI off Sourceforge. This really helped me sanity check my issue, and provided some useful pointers for the fix.
You can always just send the xml as a string and screw the libraries. Not recommended but in some cases that is easier.
don't forget the Header("SoapAction: ...")

Categories