首页 > 解决方案 > 用于正确解析包含数组中每个项目的一个子元素的 XML 元素的 PHP 函数

问题描述

我正在搜索可以解析 XML 字符串的现有或自定义函数,如下所示:

<root>
    <products>
        <product>
            <sku>001</sku>
            <name>Product 1</name>
        </product>
        <product>
            <sku>002</sku>
            <name>Product 2</name>
        </product>
    </products>
</root>

成这样的数组:

Array
(
    [products] => Array
        (
            [0] => Array
                (
                    [sku] => 001
                    [name] => Product 1
                )

            [1] => Array
                (
                    [sku] => 002
                    [name] => Product 2
                )

        )

)

我一直在使用以下内容从 XML 中获取一个不错的数组:

$arr = json_decode(json_encode(new SimpleXMLElement($xml)), true);

但是正如您所看到的,该数组带有额外的“产品”键,有点时髦:

Array
(
    [products] => Array
        (
            [product] => Array
                (
                    [0] => Array
                        (
                            [sku] => 001
                            [name] => Product 1
                        )

                    [1] => Array
                        (
                            [sku] => 002
                            [name] => Product 2
                        )

                )

        )

)

此函数应该能够解析任何大小的 xml 并以相同的方式正确格式化数组,而无需知道任何元素名称。就我而言,我不需要担心收集任何属性或类似的东西。

我一直在玩弄创建一个在解析数组时使用 Xpath 的函数的想法,但还没有成功地创建/找到一个可以按需要工作的函数。

标签: phparraysxml-parsing

解决方案


这是我不久前在将 XML 内容转换为数组时开始使用的函数。

完整的描述可以在这里找到: https ://totaldev.com/flatten-multidimensional-arrays-php/

对于您的示例,您应该能够像这样使用它:

// Flatten an array of data with full-path string keys
function flat($array, $separator = '|', $prefix = '', $flattenNumericKeys = false, $appendNumericArrayKeys = true) {
    $result = [];

    foreach($array as $key => $value) {
        $separatorKey = (empty($prefix) ? '' : $separator) . $key;
        $valueIsNumericArray = is_array($value) && count(array_filter(array_keys($value), 'is_string')) < 1;
        if($appendNumericArrayKeys === false && $valueIsNumericArray) $separatorKey = '';
        $new_key = $prefix . $separatorKey;

        // Make sure value isn't empty
        if(is_array($value)) {
            if(empty($value)) $value = null;
            else if(count($value) == 1 && isset($value[0]) && is_string($value[0]) && empty(trim($value[0]))) $value = null;
        }

        $hasStringKeys = is_array($value) && count(array_filter(array_keys($value), 'is_string')) > 0;
        if(is_array($value) && ($hasStringKeys || $flattenNumericKeys)) $result = array_merge($result, flat($value, $separator, $new_key, $flattenNumericKeys, $appendNumericArrayKeys));
        else $result[$new_key] = $value;
    }

    return $result;
}

它基本上将您从 XML 中获得的数组扁平化为一个数组,其中的键是元素的字符串路径。你会像这样使用它:

$arr = json_decode(json_encode(new SimpleXMLElement($xml)), true);
$flattenedArray = flat($arr, '|', '', false, false);
echo '<pre>'.print_r($flattenedArray, true).'</pre>';

展平数组的输出如下所示:

Array
(
    [products] => Array
        (
            [0] => Array
                (
                    [sku] => 001
                    [name] => Product 1
                )

            [1] => Array
                (
                    [sku] => 002
                    [name] => Product 2
                )

        )

)

推荐阅读