Php:将平面阵列转换为树状结构

时间:2013-03-03 18:13:59

标签: php xml arrays sorting

我需要有关阵列转换的帮助。我有一个看起来像这样的平面阵列:

Array
(
[0] =>  av_one_third
[1] =>  av_icon_box
[2] =>  /av_icon_box
[3] =>  av_button
[4] =>  av_icon_box
[5] =>  /av_icon_box
[6] =>  /av_one_third

)

此数组的值实际上是来自类似xml的结构的标记。我现在需要的是将此数组转换为类似于以下结构的嵌套数组:

[0] => Array
    (
        [tag] => av_one_third
        [content] => Array
            (
                [1] => Array
                    (
                        [tag] => av_icon_box
                        [content] => Array
                            (
                            )

                    )

                [2] => Array
                    (
                        [tag] => av_button
                        [content] => Array
                            (
                            )

                    )  

                [3] => Array
                    (
                        [tag] => av_icon_box
                        [content] => Array
                            (
                            )

                    )


            )

    )
etc

有一种简单的方法吗?我的第一个想法是将数组转换为xml字符串并使用phps本机XML函数之一,但问题是自闭标签没有标记为这样。在上面的例子中,av_button标签没有关闭标签抛出我试过的xml解析函数。

一些额外要求: - 元素可以容纳任意数量的孩子 - 最终数组必须保持正确的顺序

是否有可以轻松解决此问题的智能阵列排序功能? 将不胜感激任何暗示!

最好的问候:)

1 个答案:

答案 0 :(得分:1)

您的数组具有编码层次结构的典型平面结构。但只有你在那里修复错误。

它基本上与以下列表中的PHP代码一样,包括异常告诉数据中的错误,以便您可以修复数据(您可以在此网站上找到类似示例,例如查看{{3中的链接问题}}):

  1. 初始化树阵列中的根条目。在那里你可以添加孩子。

    $tree     = ['children' => []];
    
  2. 创建一个指向树的指针数组,其第一个元素(级别0)指向树的根元素:

    $pointers = [&$tree];
    
  3. 现在查看数据中的每一行:

    foreach ($data as $index => $line) {
    
  4. 决定该行是否关闭并存储决策结果:

    $close = '/' === $line[0];
    
  5. 存储指针的当前计数:

    $count = count($pointers);
    
  6. 如果该行没有关闭,请打开一个新元素并继续:

    $pointers[$count]                   = ['tag' => $line, 'children' => []];
    $pointers[$count - 1]['children'][] = & $pointers[$count];
    continue;
    
  7. 如果该行确实关闭,请验证标记名是否匹配,如果是,则删除最后创建的指针:

    if ($count === 1) {
        throw new RuntimeException('Can not close on lowest level.');
    }
    
    $name = $pointers[$count - 1]['tag'];
    
    if ($name !== substr($line, 1)) {
        throw new RuntimeException(
            "Invalid closing element <$line> (line #$index) in <$name>"
        );
    }
    
    array_pop($pointers);
    
  8. 在处理完所有行之后,可以删除所有指针:

    unset($pointers);
    
  9. 结果是可以在根节点中的第一个子节点中找到的数组。它可以分配给变量,然后可以删除不需要的引用:

    $result = &$tree['children'][0];
    unset($tree);
    print_r($result);
    
  10. 如果数据正确,则为示例输出:

    Array
    (
        [tag] => av_one_third
        [children] => Array
            (
                [0] => Array
                    (
                        [tag] => av_icon_box
                        [children] => Array
                            (
                            )
                    )
                [1] => Array
                    (
                        [tag] => av_button
                        [children] => Array
                            (
                            )
                    )
                [2] => Array
                    (
                        [tag] => av_icon_box
                        [children] => Array
                            (
                            )
                    )
            )
    )