最常用、可靠的方式是用递归函数手动遍历并构建数组,能准确区分属性、文本、子节点并处理重复标签;而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 = '张三 - a
- b
';
$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 中转,写个十几行递归函数反而更稳、更可控。
立即学习“PHP免费学习笔记(深入)”;











