XML разбора: теги должны быть в числовом массиве? - PullRequest
0 голосов
/ 19 января 2010
<?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>

против

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

, результирующий массив не согласован.А именно, в первом случае он имеет формат:

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

В то время как во втором случае он имеет формат:

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

Что я здесь говорю, так это то, чтоиндексировать элементы sub-xml численно, что мне и нужно, но только когда их больше 1. Любые мысли о том, что следует изменить, чтобы они всегда были проиндексированы численно, а не прямая ссылка на один-единственный элемент @массив атрибутов?

Любая помощь будет принята с благодарностью: D

Ответы [ 2 ]

0 голосов
/ 19 января 2010

бах! Я поиграл с парой кода ниже в течение пары часов и, наконец, выбил его из редактора! хитрость заключалась в том, чтобы перебирать переменные с ссылками на значения, и если это действительно был объект, но ключ не был «@attributes» (как упоминалось выше), то оберните его в массив:

/**
 * 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;
}
0 голосов
/ 19 января 2010

Ну, у вас не может быть элемента или атрибута, который является int, поэтому просто протестируйте ключ массива 0 и затем подделайте ожидаемый массив, чтобы он работал.

...