将多维数组转换为XML

7
请在您评论这可能是重复的内容之前,先阅读下面加粗的行。这与SimpleXML无关。
我先展示一下XML应该如何布局,请忽略命名空间:
 <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>

请注意在hot1:RoomsInformation下有RoomInfo。我应该能够发送多个RoomInfo节点。但我正在使用PHP类将数组转换为此对象以通过SOAP提交。

在它被转换为对象之前,这是我的数组:

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

问题在于转换为对象后,只有一个RoomInfo,而且是最后一个。我的想法是因为RoomsInformation数组有2个相同的KEY名称。那么我该如何解决这个问题呢?
供您参考,这是我使用的SOAP类和arrayToObject函数: http://pastebin.com/SBUN0FAF

3
可能是与如何将数组转换为SimpleXML相似的重复问题。 - sectus
1
如果您使用SOAP,则php内置的SoapClient可以处理数组。 - Fracsi
2
你不能这样做,因为数组里的元素是无法区分的。无论你有多少个“RoomsInformation”条目,如果它们具有相同的键,则它们实际上只是一个。 - Rolando Isidoro
另一个可能相关的问题是:如何使用数组更新SimpleXMLElement - hakre
请查看我在问题末尾添加的编辑。 - swg1cor14
显示剩余5条评论
3个回答

14

问题是,正如您所怀疑的那样,由于重复键,您的数组无效。解决此问题的一种方法是将每个“RoomInfo”都包装在自己的数组中,如下所示:

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

您可以像这样生成XML:

// 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");
        }
    }
}

我把 array_to_xml 函数归功于这位了不起的作者:https://dev59.com/6XM_5IYBdhLWcg3wZSI6#5965940


1
不使用SimpleXML。我必须将其转换为对象以通过SOAP客户端发送。按照您建议的更改会使两个RoomsInfo完全消失。 - swg1cor14

0

看起来你应该像这样设定数组:

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

这将保留两个RoomInfo数组元素。


-1

只需使用此函数,其中 $data 是多维数组

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();
     }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接