Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert multidimensional array into XML

Tags:

object

php

xml

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

like image 381
swg1cor14 Avatar asked Jul 02 '13 14:07

swg1cor14


Video Answer


1 Answers

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

like image 143
chrislondon Avatar answered Sep 22 '22 11:09

chrislondon