从包含重复元素的XML转换PHP数组

fir*_*ace 7 php xml arrays

到目前为止,我一直在使用下面的代码片段将XML树转换为数组:

$a = json_decode(json_encode((array) simplexml_load_string($xml)),1);
Run Code Online (Sandbox Code Playgroud)

..但是,我现在正在使用具有重复键值的XML,因此当它循环遍历XML时,数组就会中断.例如:

<users>
    <user>x</user>
    <user>y</user>
    <user>z</user>
</users>
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来执行此操作以允许重复键,或者可能是一种在每个键吐出数组时为每个键添加递增值的方法,如下所示:

$array = array(
    users => array(
        user_1 => x,
        user_2 => y,
        user_3 => z
    )
)
Run Code Online (Sandbox Code Playgroud)

我很难过,所以任何帮助都会非常感激.

cpu*_*rou 2

这是一个完整的通用递归解决方案。

此类将解析任何结构下的任何 XML,无论有或没有标签,从最简单的到最复杂的。

它保留所有正确的值并转换它们(bool、txt 或 int),为所有元素组(包括标签)生成足够的数组键,保留重复元素等......

请原谅静态数据,它是我使用的大型 XML 工具集的一部分,在为 HHVM 或 pthreads 重写它们之前,我没有时间正确构建这个工具,但它对于简单的 PHP 来说就像一个魅力。

对于标签,在本例中声明的值为“@attr”,但可以是您需要的任何值。

$xml = "<body>
             <users id='group 1'>
               <user>x</user>
               <user>y</user>
               <user>z</user>
             </users>
            <users id='group 2'>
               <user>x</user>
               <user>y</user>
               <user>z</user>
            </users>
        </body>";

$result = xml_utils::xml_to_array($xml);
Run Code Online (Sandbox Code Playgroud)

结果:

Array ( [users] => Array ( [0] => Array ( [user] => Array ( [0] => x [1] => y [2] => z ) [@attr] => Array ( [id] => group 1 ) ) [1] => Array ( [user] => Array ( [0] => x [1] => y [2] => z ) [@attr] => Array ( [id] => group 2 ) ) ) )
Run Code Online (Sandbox Code Playgroud)

班级:

class xml_utils {

    /*object to array mapper */
    public static function objectToArray($object) {
        if (!is_object($object) && !is_array($object)) {
            return $object;
        }
        if (is_object($object)) {
            $object = get_object_vars($object);
        }
        return array_map('objectToArray', $object);
    }

    /* xml DOM loader*/
    public static function xml_to_array($xmlstr) {
        $doc = new DOMDocument();
        $doc->loadXML($xmlstr);
        return xml_utils::dom_to_array($doc->documentElement);
    }

    /* recursive XMl to array parser */
    public static function dom_to_array($node) {
        $output = array();
        switch ($node->nodeType) {
            case XML_CDATA_SECTION_NODE:
            case XML_TEXT_NODE:
                $output = trim($node->textContent);
                break;
            case XML_ELEMENT_NODE:
                for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) {
                    $child = $node->childNodes->item($i);
                    $v = xml_utils::dom_to_array($child);
                    if (isset($child->tagName)) {
                        $t = xml_utils::ConvertTypes($child->tagName);
                        if (!isset($output[$t])) {
                            $output[$t] = array();
                        }
                        $output[$t][] = $v;
                    } elseif ($v) {
                        $output = (string) $v;
                    }
                }
                if (is_array($output)) {
                    if ($node->attributes->length) {
                        $a = array();
                        foreach ($node->attributes as $attrName => $attrNode) {
                            $a[$attrName] = xml_utils::ConvertTypes($attrNode->value);
                        }
                        $output['@attr'] = $a;
                    }
                    foreach ($output as $t => $v) {
                        if (is_array($v) && count($v) == 1 && $t != '@attr') {
                            $output[$t] = $v[0];
                        }
                    }
                }
                break;
        }
        return $output;
    }

    /* elements converter */
    public static function ConvertTypes($org) {
        if (is_numeric($org)) {
            $val = floatval($org);
        } else {
            if ($org === 'true') {
                $val = true;
            } else if ($org === 'false') {
                $val = false;
            } else {
                if ($org === '') {
                    $val = null;
                } else {
                    $val = $org;
                }
            }
        }
        return $val;
    }

}
Run Code Online (Sandbox Code Playgroud)