7

Please read the bolded line below before you comment that this may be a duplicate. This has nothing to do with SimpleXML.

Let me start off by showing how the XML should be laid out. Please ignore the namespaces:

 <hot:SearchHotels>
     <hot:request>
        <hot1:Destination>?</hot1:Destination>
        <hot1:HotelCityName>?</hot1:HotelCityName>
        <hot1:HotelLocationName>?</hot1:HotelLocationName>
        <hot1:HotelName>?</hot1:HotelName>
        <hot1:CheckIn>?</hot1:CheckIn>
        <hot1:CheckOut>?</hot1:CheckOut>
        <hot1:RoomsInformation>
           <!--Zero or more repetitions:-->
           <hot1:RoomInfo>
              <hot1:AdultNum>?</hot1:AdultNum>
              <hot1:ChildNum>?</hot1:ChildNum>
              <!--Optional:-->
              <hot1:ChildAges>
                 <!--Zero or more repetitions:-->
                 <hot1:ChildAge age="?"/>
              </hot1:ChildAges>
           </hot1:RoomInfo>
        </hot1:RoomsInformation>
        <hot1:MaxPrice>?</hot1:MaxPrice>
        <hot1:StarLevel>?</hot1:StarLevel>
        <hot1:AvailableOnly>?</hot1:AvailableOnly>
        <hot1:PropertyType>?</hot1:PropertyType>
        <hot1:ExactDestination>?</hot1:ExactDestination>
     </hot:request>
  </hot:SearchHotels>

Notice under hot1:RoomsInformation there is RoomInfo. I'm supposed to be able to send multiple RoomInfo nodes. But I'm using a PHP class to convert an array to this object to be submitted via SOAP.

Here's my array before it gets converted to an object:

$param = array(
            "Destination" => $destcode,
            "HotelCityName" => $city,
            "HotelLocationName" => "",
            "HotelName" => "",
            "CheckIn" => date("Y-m-d", strtotime($checkin)),
            "CheckOut" => date("Y-m-d", strtotime($checkout)),
            "RoomsInformation" => array (
                "RoomInfo" => array(
                        "AdultNum" => 2,
                        "ChildNum" => 1,
                        "ChildAges" => array(
                            "ChildAge" => array(
                                "age"=>11
                            )
                        )
                    ),
                "RoomInfo" => array(
                        "AdultNum" => 1,
                        "ChildNum" => 0,
                        "ChildAges" => array(
                            "ChildAge" => array(
                                "age"=>0
                            )
                        )
                    )
            ),
            "MaxPrice" => 0,
            "StarLevel" => 0,
            "AvailableOnly" => "false",
            "PropertyType" => "NotSet",
            "ExactDestination" => "false"
        );

$param = arrayToObject($param) ;
$obj = new stdClass(); 
$obj->request=$param;
$result = $test->SearchHotels($obj) ;

The problem is that after converting to an Object, there is only 1 RoomInfo and its the last one. My thought is because the RoomsInformation array has 2 identical KEY names. So how can I make this work?

For your information, here is the SOAP class I use and the arrayToObject function:

http://pastebin.com/SBUN0FAF

swg1cor14
  • 1,682
  • 6
  • 25
  • 46
  • 3
    possible duplicate of [How to convert array to SimpleXML](http://stackoverflow.com/q/1397036/1503018) – sectus Jul 02 '13 at 14:31
  • 1
    If you use SOAP, then the php built-in SoapClient can handle the array – Fracsi Jul 02 '13 at 14:33
  • 2
    You can't, not with that array. No matter how many `RoomsInformation` entries you have, if they have the same key they are indeed just one. – Rolando Isidoro Jul 02 '13 at 14:54
  • Another portential related question is: [How to update SimpleXMLElement using array](http://stackoverflow.com/q/14836849/367456) – hakre Jul 03 '13 at 04:10
  • Thanks for pointing out the duplicates. However I've already looked at those and they didnt have to do with what I'm trying to do. I'm not trying to use SimpleXML. I'm trying to convert to an object for use with SOAP – swg1cor14 Jul 03 '13 at 13:37
  • Please see the edit I added to the end of my question – swg1cor14 Jul 03 '13 at 13:58
  • @swg1cor14: The definition of the function `arrayToObject()` is missing in your question. Create it in a way, that your question contains a *minimal self-contained* example code that allows it to be reproduced easily (if you're looking for an answer). Reduce the problem to the bare minimum otherwise it's likely that your question is too individual and doesn't fit well this Q&A site. Thanks for the edit so far, I actually can start to see what you're after however it's not yet totally clear (and especially not easy to reproduce). Is `$test` a `SoapClient`? – hakre Jul 04 '13 at 16:09
  • Yes I'm sorry I left that line out. It is calling new FixSoapClient() – swg1cor14 Jul 08 '13 at 18:07
  • If you got response from XML, can you give send me code? I stuck with same problem. I have also added questions in stackoverflow, links are http://stackoverflow.com/questions/21675263/curl-not-working-for-soap-enveloped-xml-request and http://stackoverflow.com/questions/21521785/soap-request-for-tourico-webservice-implementation?lq=1 – Jimesh Gajera Feb 11 '14 at 13:43
  • I am very thankful to you if you can send me code on my email id jimesh.gajera@gmail.com – Jimesh Gajera Feb 11 '14 at 13:51

3 Answers3

14

The problem is, your array is invalid as you suspected because of the duplicate keys. One way to solve the issue is to wrap each "RoomInfo" in its own array like so:

$param = array(
    "Destination" => $destcode,
    "HotelCityName" => $city,
    "HotelLocationName" => "",
    "HotelName" => "",
    "CheckIn" => date("Y-m-d", strtotime($checkin)),
    "CheckOut" => date("Y-m-d", strtotime($checkout)),
    "RoomsInformation" => array (
        array(
            "RoomInfo" => array(
                "AdultNum" => 2,
                "ChildNum" => 1,
                "ChildAges" => array(
                    "ChildAge" => array(
                        "age"=>11
                    )
                )
            ),
        ),
        array(
            "RoomInfo" => array(
                "AdultNum" => 1,
                "ChildNum" => 0,
                "ChildAges" => array(
                    "ChildAge" => array(
                        "age"=>0
                    )
                )
            )
        )
    ),
    "MaxPrice" => 0,
    "StarLevel" => 0,
    "AvailableOnly" => "false",
    "PropertyType" => "NotSet",
    "ExactDestination" => "false"
);

And you can generate the XML like this:

// create simpleXML object
$xml = new SimpleXMLElement("<?xml version=\"1.0\"?><SearchHotels></SearchHotels>");
$node = $xml->addChild('request');

// function call to convert array to xml
array_to_xml($param, $node);

// display XML to screen
echo $xml->asXML();
die();

// function to convert an array to XML using SimpleXML
function array_to_xml($array, &$xml) {
    foreach($array as $key => $value) {
        if(is_array($value)) {
            if(!is_numeric($key)){
                $subnode = $xml->addChild("$key");
                array_to_xml($value, $subnode);
            } else {
                array_to_xml($value, $xml);
            }
        } else {
            $xml->addChild("$key","$value");
        }
    }
}

I attribute the array_to_xml function to the wonderful author here: https://stackoverflow.com/a/5965940/2200766

Community
  • 1
  • 1
chrislondon
  • 12,487
  • 5
  • 26
  • 65
  • 1
    Not trying to use SimpleXML. I have to convert to an object to send via SOAP Client. Making the changes you suggested makes both RoomsInfo disappear altogether. – swg1cor14 Jul 03 '13 at 13:47
0

It looks as though you should have your array like this, instead;

$param = array(
        "Destination" => $destcode,
        "HotelCityName" => $city,
        "HotelLocationName" => "",
        "HotelName" => "",
        "CheckIn" => date("Y-m-d", strtotime($checkin)),
        "CheckOut" => date("Y-m-d", strtotime($checkout)),
        "RoomsInformation" => array (
            "RoomInfo" => array(
                  array(
                    "AdultNum" => 2,
                    "ChildNum" => 1,
                    "ChildAges" => array(
                        "ChildAge" => array(
                            "age"=>11
                        )
                    )
                  ),
                  array(
                    "AdultNum" => 1,
                    "ChildNum" => 0,
                    "ChildAges" => array(
                        "ChildAge" => array(
                            "age"=>0
                        )
                    )
                )
            )
        ),
        "MaxPrice" => 0,
        "StarLevel" => 0,
        "AvailableOnly" => "false",
        "PropertyType" => "NotSet",
        "ExactDestination" => "false"
    );

This will preserve the two RoomInfo array elements.

Tim
  • 1
-1

simply use this function, where $data is multideminsional array

function array_to_xml( $data ) {
         $xml_data = new SimpleXMLElement('<?xml version="1.0"?><data></data>');

         foreach( $data as $key => $value ) {
           $node = $xml_data->addChild('row_' . $key);

           foreach( $value as $keyx => $valuex ) {
             $node->addChild($keyx,$valuex);
            }


          }
          return $xml_data->asXML();
     }
Malek Tubaisaht
  • 1,170
  • 14
  • 16