web-dev-qa-db-ja.com

SOAP XML応答をPHPオブジェクトまたは配列に変換する

CURLを使用してリクエストをSOAPサービスに送信し、POST本文にパラメーターを含むXMLを送信し、受信した応答として:

Webサービス: 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);
10
Hamza

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;

その要素には接頭辞が付いていないためです。より複雑な結果が返されるので、すべての応答値に簡単にアクセスできるため、これがおそらく最良です。

あなたの質問は次のようになります:

たぶん、そこにあるコード/説明も役に立ちます。

9
hakre

SOAP応答をDOMドキュメントに渡して、それを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;
?>

ただし、これにより、応答の特殊文字(éやàなど)で問題が発生する可能性があります。そうでなければ、それは機能します。

9
shasi kanth

別の解決策、私のために働いた唯一の解決策:

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

楽しい :)

3
Jerry

うーん。 SOAPクライアントを使用して、SOAPリクエストを送信するだけでなく、それを行う必要があります。PHPは統合されていますSOAP機能 http://php.net/manual/en/book.soap.php

NuSOAPのようなカスタムsoapライブラリがあります http://sourceforge.net/projects/nusoap/

ほとんどのphpフレームワークにはSOAPライブラリもあります。

2
bksi