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

时间:2013-04-09 03:11:41

标签: php xml web-services soap simplexml

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

网络服务: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);

4 个答案:

答案 0 :(得分:9)

bksi的提示并没有错,但从技术上来说,这是XML,你只需要正确访问命名空间元素。通过使用XPath表达式并将namspace-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;

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

您的问题类似于:

也许这些代码/描述也很有帮助。

答案 1 :(得分:9)

您可以考虑通过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;
?>

但是,这可能会导致您的回复中出现特殊字符问题,例如é和à。否则,它有效。

答案 2 :(得分:2)

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

有像NuSOAP这样的自定义肥皂库 http://sourceforge.net/projects/nusoap/

大多数php框架也都有SOAP库。

答案 3 :(得分:2)

另一种解决方案,唯一对我有用的解决方案:

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

享受:)