将SOAP XML响应转换为PHP对象或数组


converting SOAP XML response to a PHP object or array

我使用cURL向SOAP服务发送请求,我在POST Body中发送包含参数的XML,作为响应,我收到:

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>

我对XML数据没有足够的经验。我花了几个小时尝试将XML响应转换为PHP对象或数组,但没有成功。

我需要读取所有PropertyResults.

PHP代码:

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

另一个解决方案,对我来说唯一有效的解决方案:

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

享受:)

bksi的提示并没有错,但是从技术上讲,因为这是XML,您只需要正确地访问名称空间元素。使用XPath表达式并将名称空间uri注册到您自己的前缀:

$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);
输出:

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"

如果不想使用XPath,则需要在遍历时指定名称空间,如果元素本身没有前缀,则只有元素本身名称空间中的子元素可以直接使用。由于根元素有前缀,您首先需要遍历到响应:

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

那么你可以使用$response变量,因为你知道它:

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

,因为该元素没有前缀。由于返回更复杂的结果,这可能是最好的,因为您可以轻松访问所有响应值。

你的问题类似于:

  • 用PHP解析SOAP响应中的CDATA

也许这里的代码/描述也有帮助。

您可以考虑通过DOM Document传递SOAP响应,然后将其转换为simplexml对象。

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

但是,这可能会导致响应中的特殊字符出现问题,例如:

您应该使用SOAP客户机来完成此操作,而不仅仅是发送SOAP请求。PHP集成了SOAP功能http://php.net/manual/en/book.soap.php。

有自定义soap库,如NuSOAPhttp://sourceforge.net/projects/nusoap/。

大多数php框架也有SOAP库