17370845950

PHP怎么把XML对象转换成数组
最常用、可靠的方式是用递归函数手动遍历并构建数组,能准确区分属性、文本、子节点并处理重复标签;而json_decode(json_encode((array)$xml), true)易丢失属性、覆盖同名节点,仅适用于无属性无重复的简单场景。

PHP 将 XML 对象(SimpleXMLElement)转成数组,最常用、可靠的方式是用递归函数手动遍历并构建数组。因为 json_decode(json_encode((array)$xml), true) 这种“伪转换”在属性、文本混合、重复子节点、CDATA 等场景下容易出错或丢失数据。

用递归函数安全转换(推荐)

这个方法能准确区分元素属性、文本内容、子节点,并保留结构层次:

function xmlToArray($xml) {
    if (!($xml instanceof SimpleXMLElement)) {
        return $xml;
    }

    $array = [];
    // 处理属性
    $attributes = $xml->attributes();
    if ($attributes && count($attributes) > 0) {
        foreach ($attributes as $attr => $value) {
            $array['@attributes'][$attr] = (string)$value;
        }
    }

    // 处理子节点(含文本节点)
    $children = $xml->children();
    if (count($children) > 0) {
        foreach ($children as $childName => $child) {
            $childArray = xmlToArray($child);
            if (!isset($array[$childName])) {
                $array[$childName] = $childArray;
            } else {
                // 同名子节点多个时转为数组(避免覆盖)
                if (!is_array($array[$childName]) || !isset($array[$childName][0])) {
                    $array[$childName] = [$array[$childName]];
                }
                $array[$childName][] = $childArray;
            }
        }
    } else {
        // 只有文本内容(无子节点)
        $text = trim((string)$xml);
        if ($text !== '' || isset($array['@attributes'])) {
            $array['#text'] = $text;
        }
    }

    return $array;
}

// 使用示例
$xmlStr = '张三ab';
$xml = simplexml_load_string($xmlStr);
$result = xmlToArray($xml);
print_r($result);

处理简单 XML(无属性、无重复标签)可快速转换

如果 XML 结构非常规整(比如全是单层子节点、无属性、无同名多节点),可用更简方式:

  • 先转 JSON 再解码:$arr = json_decode(json_encode($xml), true);
  • 但注意:它会把属性丢掉,同名子节点只保留最后一个,文本和子节点混同时行为不可控
  • 仅适合测试或内部简单配置类 XML,不建议用于生产环境解析外部 XML

注意事项和常见坑

  • SimpleXMLElement 不是标准对象:不能直接用 (array)$xml 强转,会丢失结构信息
  • 同名子节点会被覆盖:必须手动判断是否已存在,再转为数组,否则第二个 会覆盖第一个
  • 空元素或纯属性元素:如 ,需靠 @attributes#text 区分逻辑
  • 命名空间 XML:加载时要用 simplexml_load_string($xml, null, LIBXML_NOBLANKS, 'ns') 并在递归中调用 $xml->children('ns', true)

基本上就这些。核心是别图省事用 json 中转,写个十几行递归函数反而更稳、更可控。