xml解析:标签应该是数字数组?

时间:2010-01-19 01:31:21

标签: php xml arrays recursion traversal

<?php
/*
    Sample: $results = XMLParser::load('<xml ....');
            $results = XMLParser::load(VSCHEMAS.'/Users.edit.xml');
*/

    /**
     * Abstract XMLParser class. A non-instantiable class that uses SimpleXML to parse XML, based on a path or body passed into the load method
     * 
     * @abstract
     */
    abstract class XMLParser {

        /**
         * convert function. Converts a SimpleXMLElement object to an associative array, usable for iteration
         * 
         * @see http://www.if-not-true-then-false.com/2009/12/php-tip-convert-stdclass-object-to-multidimensional-array-and-convert-multidimensional-array-to-stdclass-object/
         * @access private
         * @static
         * @param mixed $node node to convert to a non-object based value
         * @return array associative array of the passed in node/object, ultimately representing the initially passed in object as an associative array
         */
        private static function convert($node) {
            if(is_object($node))
                $node = get_object_vars($node);
            if(is_array($node))
                return array_map(array('self', 'convert'), $node);
            return $node;
        }

        /**
         * load function. Loads a source (either a local path or source body) document, and returns as associative array of it's results
         * 
         * @access public
         * @static
         * @param string $source xml body, or path to local xml file
         * @return array SimpleXML results, parsed as an associative array
         */
        public static function load($source) {
            $path = false;
            if(preg_match('/^\//', $source) > 0)
                $path = true;
            $simpleXMLElement = new SimpleXMLElement($source, LIBXML_NOENT, $path);
            return self::convert($simpleXMLElement);
        }
    }

?>

我正在使用上面的代码来解析xml文件并将它们转换为更易遍历的数组。我遇到了一个问题。当我有一些样本xml如:

<fields>
    <rule whatever="lolcats" />
</fields>

VS

<fields>
    <rule whatever="lolcats" />
    <rule whatever="lolcats" />
</fields>

结果数组不一致。也就是说,在第一种情况下,它的格式为:

Array
(
    [field] => Array
        (
            [@attributes]...

而在后者中,它的格式为:

Array
(
    [field] => Array
        (
            [0]...

我在这里说的是,它是以数字方式索引子xml元素,这就是我想要的,但只有在超过1的情况下。任何想要改变的想法总是让它们用数字索引,而不是而不是直接引用唯一元素的@attributes数组?

非常感谢任何帮助:D

2 个答案:

答案 0 :(得分:0)

你不能拥有一个int的元素或属性,所以只需测试数组键0然后伪造你期望应该工作的数组。

答案 1 :(得分:0)

热潮!我玩了几个小时的代码,最后把它从编辑器中删除了!诀窍是循环使用值为引用的变量,如果它确实是一个对象,但键不是'@attributes'(如上所述),则将其包装在一个数组中:D

/**
 * convert function. Converts a SimpleXMLElement object to an associative array, usable for iteration
 * 
 * @see http://www.if-not-true-then-false.com/2009/12/php-tip-convert-stdclass-object-to-multidimensional-array-and-convert-multidimensional-array-to-stdclass-object/
 * @access private
 * @static
 * @param mixed $node node to convert to a non-object based value
 * @return array associative array of the passed in node/object, ultimately representing the initially passed in object as an associative array
 */
private static function convert($node) {
    if(is_object($node)) {
        $vars = get_object_vars($node);
        foreach($vars as $key => &$var) {
            if($key!=='@attributes' && is_object($var))
                $var = array($var);
        }
        $node = $vars;
    }
    if(is_array($node))
        return array_map(array('self', 'convert'), $node);
    return $node;
}