如何将PHP SimpleXML子节点放入数组中的数组中

时间:2015-04-05 21:02:23

标签: php arrays xml xml-parsing simplexml

问题背景

我有一个大型XML文件,我试图将其解析为PHP数组。

我的文件结构就是这样

<orders>
  <order>
    <value1></value1>
    <value2></value3>
    <value2></value3>
    <items>
      <item></item>
      <price></price>
    </items>
  </order>
</orders>

等等更多的价值观。 我的PHP函数看起来像这个

public function outputNodes() {
    // this function creates/returns an array of all the XML nodes and child nodes
    // we do not know how many custom attributes there may be for orders, so this
    // handles them programmatically with count

if (file_exists($this->getFilePath())) { // this checks to make sure there is a file

    $orders = array(); //create blank array for orders

    $obj = $this->getXML($this->getFilePath()); // start by getting XML object

    $order = $obj->children();
    $oCount = count($order);  //How many orders are there?

    $topNodes = $obj->order->children();
    $topNodesCount = count($topNodes); //How many nodes does each order have?

    //begin looping through orders

    for($i=0;$i<$oCount;$i++) {

        $vals = array(); //for each order create the array to store the values of items node

         foreach($topNodes as $key => $value) { //for each top level nodes do something

             if((string)$key == "items"){ //checks to see if this top level node is the items node
                $cobj = $obj->order->items->children(); //if it is create object of the children of node
                foreach($cobj as $k =>$v) { //for each child of items node do something
                    $v[(string)$k] = (string)$v; //creates a temporary array of the child names/values of items node
                    }
                $vals[] = $v; //places them into $vals array
                $ord[(string)$key] = $vals; //places entire $vals array into temp ord array for output
                }
            else {
            $ord[(string)$key] = (string)$value;
            }           
         }
         $orders[] = $ord;
    }
    return $orders;
}
 else {
     return "Error";
     }
}

现在要清楚,这段代码在理论上工作得很好,它确实将$ vals []数组放入$ orders []数组中,但是这样做是这样的:

[items] => Array ( [0] => SimpleXMLElement Object ( [@attributes] => Array ( [item] => ) [item_name] => Nameof Product [item_price] => $8.00 [item_quantity] => 12 ) ) )

问题

那么我有两个问题。首先,我如何阻止它将Array ( [0] => SimpleXMLElement Object ( [@attributes]这个错误信息放入?

其次,更重要的是,如何修改代码,而不是必须按名称调用items节点,我宁愿让它检查任何给定节点是否有更多孩子们会自动把它们拉成阵列吗?

我希望每次有更多子节点时都不必编写新代码并只需检查:是否有子节点?如果是,请获取它们并将其显示在嵌套数组中

提前致谢

1 个答案:

答案 0 :(得分:1)

实现这一目标的一种方法是迭代文档中的所有元素,然后根据数据流构建数组:

$builder = new StructureBuilder();

foreach ($xml->xpath('//*') as $element) {
    $depth  = count($element->xpath("./ancestor::*"));
    $builder->add($depth, $element->getName(), trim($element));
}

print_r($builder->getStructure());

使用您的示例数据,这是:

Array
(
    [orders] => Array
        (
            [order] => Array
                (
                    [value1] => 
                    [value2] => 
                    [value3] => 
                    [items] => Array
                        (
                            [item] => 
                            [price] => 
                        )

                )

        )

)

它是如何工作的? StructureBuilder 会跟踪结构中哪个元素为$depth做好准备。你可以find the full example code as gist

您还可以看到之前的答案PHP Parse XML response with many namespaces,该答案也询问了如何转换。关于缩进的例子有更多冗长。