converting SOAP XML response to a PHP object or ar

2019-01-09 01:47发布

问题:

I'm using cURL to send an request to a SOAP service, I send in POST Body the XML containing parameters, in response I receive:

Web service: http://lcbtestxmlv2.ivector.co.uk/soap/book.asmx?WSDL

<?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>
          <SearchResponse xmlns="http://ivectorbookingxml/">
             <SearchResult>
                <ReturnStatus>
                   <Success>true</Success>
                   <Exception />
                </ReturnStatus>
                <SearchURL>http://www.lowcostholidays.fr/dl.aspx?p=0,8,5,0&amp;date=10/05/2013&amp;duration=15&amp;room1=2,1,0_5&amp;regionid=9</SearchURL>
                <PropertyResults>
                   <PropertyResult>
                      <TotalProperties>215</TotalProperties>
                      <PropertyID>1795</PropertyID>
                      <PropertyName>Hotel Gaddis</PropertyName>
                      <Rating>3.0</Rating>
                      <Country>Egypte</Country>
                      <Resort>Louxor</Resort>
                      <Strapline>Cet établissement confortable propose un très bon service à un bon rapport qualité-prix. Cet hôtel de 6 étages compte 55 chambres et comprend une terrasse, une réception avec coffre-fort et ascenseur,</Strapline>
                      <Description>Cet établissement confortable propose un très bon service à un bon rapport qualité-prix. Cet hôtel de 6 étages compte 55 chambres et comprend une terrasse, une réception avec coffre-fort et ascenseur,...</Description>
                      <CMSBaseURL>http://lcbtestxml1.ivector.co.uk/content/DataObjects/Property/Image/</CMSBaseURL>
                      <MainImage>image_1795_v1.jpg</MainImage>
                      <MainImageThumbnail>imagethumb_1795_v1.jpg</MainImageThumbnail>
                      <SearchURL>http://www.lowcostholidays.fr/dl.aspx?p=0,8,5,0&amp;date=10/05/2013&amp;duration=15&amp;room1=2,1,0_5&amp;regionid=9&amp;propertyid=1795</SearchURL>
                      <RoomTypes>
                         <RoomType>
                            <Seq>1</Seq>
                            <PropertyRoomTypeID>690039000</PropertyRoomTypeID>
                            <MealBasisID>3</MealBasisID>
                            <RoomType>Twin/double Room</RoomType>
                            <RoomView />
                            <MealBasis>Petit Déjeuner</MealBasis>
                            <NonRefundableRates>false</NonRefundableRates>
                            <SubTotal>150.58</SubTotal>
                            <Discount>0</Discount>
                            <Total>150.58</Total>
                            <Adults>2</Adults>
                            <Children>1</Children>
                            <Infants>0</Infants>
                            <Errata />
                         </RoomType>
                         <RoomType>
                            <Seq>1</Seq>
                            <PropertyRoomTypeID>690039001</PropertyRoomTypeID>
                            <MealBasisID>7</MealBasisID>
                            <RoomType>Twin/double Room</RoomType>
                            <RoomView />
                            <MealBasis>Demi-Pension</MealBasis>
                            <NonRefundableRates>false</NonRefundableRates>
                            <SubTotal>291.64</SubTotal>
                            <Discount>0</Discount>
                            <Total>291.64</Total>
                            <Adults>2</Adults>
                            <Children>1</Children>
                            <Infants>0</Infants>
                            <Errata />
                         </RoomType>
                         <RoomType>
                            <Seq>1</Seq>
                            <PropertyRoomTypeID>690039002</PropertyRoomTypeID>
                            <MealBasisID>5</MealBasisID>
                            <RoomType>Double/twin Room</RoomType>
                            <RoomView />
                            <MealBasis>Pension Complète</MealBasis>
                            <NonRefundableRates>false</NonRefundableRates>
                            <SubTotal>529.22</SubTotal>
                            <Discount>0</Discount>
                            <Total>529.22</Total>
                            <Adults>2</Adults>
                            <Children>1</Children>
                            <Infants>0</Infants>
                            <Errata />
                         </RoomType>
                      </RoomTypes>
                   </PropertyResult>
                </PropertyResults>
             </SearchResult>
          </SearchResponse>
       </soap:Body>
    </soap:Envelope>

I don't have enough experience with XML data. I spent hours trying to convert the XML response to a PHP object or array, but without any success.

I need to read all PropertyResults.

PHP Code:

$xml = simplexml_load_string($soap_xml_result);

$xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
$xml->registerXPathNamespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance');
$xml->registerXPathNamespace('xsd', 'http://www.w3.org/2001/XMLSchema');

$test = (string) $xml->Body->SearchResponse->SearchResult->SearchURL;
var_export($test);

回答1:

The hint of bksi is not that wrong, however technically as this is XML you only need to access the namespaced elements properly. This works more easy by using an XPath expression and registering the namspace-uri to your own prefix:

$soap = simplexml_load_string($soapXMLResult);
$soap->registerXPathNamespace('ns1', 'http://ivectorbookingxml/');
$test = (string) $soap->xpath('//ns1:SearchResponse/ns1:SearchResult/ns1:SearchURL[1]')[0];
var_dump($test);

Output:

string(100) "http://www.lowcostholidays.fr/dl.aspx?p=0,8,5,0&date=10/05/2013&duration=15&room1=2,1,0_5&regionid=9"

If you don't want to use XPath, you need to specify the namespace while you traverse, only the children in the namespace of the element itself are available directly if the element itself is not prefixed. As the root element is prefixed you first need to traverse up to the response:

$soap     = simplexml_load_string($soapXMLResult);
$response = $soap->children('http://schemas.xmlsoap.org/soap/envelope/')
                     ->Body->children()
                         ->SearchResponse
;

Then you can make use of the $response variable as you know it:

$test = (string) $response->SearchResult->SearchURL;

because that element is not prefixed. As a more complex result is returned this is probably the best because you can easily access all the response values.

Your question is similar to:

  • Parse CDATA from a SOAP Response with PHP

Maybe the code/descriptions there are helpful, too.



回答2:

You could consider passing the SOAP response through a DOM Document, and then converting it into a simplexml object.

<?php
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$doc->loadHTML($soap_response);
libxml_clear_errors();
$xml = $doc->saveXML($doc->documentElement);
$xml = simplexml_load_string($xml);
$response = $xml->body->envelope->body->searchresponse;
//print_r($response); exit;
echo $response->searchresult->returnstatus->success;
echo '<br>';
echo $response->searchresult->searchurl;
?>

However, this may cause problems with special characters in your response, like é and à. Else, it works.



回答3:

Hm. You should use SOAP client to do that, not just send SOAP requests. PHP has integrated SOAP functionalities http://php.net/manual/en/book.soap.php.

There are custom soap libraries like NuSOAP http://sourceforge.net/projects/nusoap/.

Most of php frameworks has SOAP libraries too.



回答4:

Another solution, the only solution that worked for me :

$xml = $soap_xml_result;
$xml = preg_replace("/(<\/?)(\w+):([^>]*>)/", '$1$2$3', $xml);
$xml = simplexml_load_string($xml);
$json = json_encode($xml);
$responseArray = json_decode($json, true); // true to have an array, false for an object
print_r($responseArray);

Enjoy :)