PHP如何完整转换含属性的XML为数组?
PHP如何将XML完整转换为包含所有属性的数组
用simplexml_load_string转XML再通过json_encode/json_decode转数组的方式确实会丢失节点属性——因为SimpleXMLElement转JSON时默认不会单独提取属性信息。PHP完全支持把XML完整转换为包含所有属性的数组,给你两个实用的实现方案:
方法一:递归遍历SimpleXMLElement构建数组
SimpleXMLElement提供了attributes()方法可以获取节点属性,我们可以写一个递归函数遍历所有节点,把属性、子节点和文本内容整合到数组中:
function xmlToArray(\SimpleXMLElement $xml): array { $result = []; // 提取节点属性 foreach ($xml->attributes() as $attrName => $attrValue) { $result['@attributes'][(string)$attrName] = (string)$attrValue; } // 处理子节点 foreach ($xml->children() as $childName => $childNode) { $childData = xmlToArray($childNode); // 若同一节点名重复出现,自动转为数组格式 if (isset($result[$childName])) { if (!is_array($result[$childName]) || !isset($result[$childName][0])) { $result[$childName] = [$result[$childName]]; } $result[$childName][] = $childData; } else { $result[$childName] = $childData; } } // 提取节点文本内容 $textContent = trim((string)$xml); if (!empty($textContent)) { if (empty($result)) { $result = $textContent; } else { $result['@value'] = $textContent; } } return $result; } // 使用示例 $xmlStr = '<root><param name="id">123</param><param name="name">test</param></root>'; $xml = simplexml_load_string($xmlStr); $array = xmlToArray($xml); print_r($array);
这个函数会把属性存储在@attributes键下,节点文本存储在@value键下,重复节点会自动转为数组结构。
方法二:用DOMDocument递归处理
如果需要更精细的控制(比如区分文本节点、CDATA块等),可以用DOMDocument来实现:
function domNodeToArray(\DOMNode $node): mixed { $result = []; // 处理元素节点的属性 if ($node instanceof \DOMElement) { foreach ($node->attributes as $attrName => $attrNode) { $result['@attributes'][$attrName] = $attrNode->value; } } // 遍历子节点 foreach ($node->childNodes as $child) { if ($child instanceof \DOMText) { $text = trim($child->nodeValue); if (!empty($text)) { if (empty($result)) { $result = $text; } else { $result['@value'] = $text; } } } elseif ($child instanceof \DOMElement) { $childData = domNodeToArray($child); $childName = $child->tagName; // 处理重复节点 if (isset($result[$childName])) { if (!is_array($result[$childName]) || !isset($result[$childName][0])) { $result[$childName] = [$result[$childName]]; } $result[$childName][] = $childData; } else { $result[$childName] = $childData; } } // 如需支持CDATA,可添加判断:elseif ($child instanceof \DOMCDATASection) } return $result; } // 使用示例 $xmlStr = '<root><param name="id">123</param><param name="name">test</param></root>'; $dom = new \DOMDocument(); $dom->loadXML($xmlStr); $array = domNodeToArray($dom->documentElement); print_r($array);
这个方案能处理更多XML节点类型,适合结构复杂的XML场景。
内容的提问来源于stack exchange,提问作者user3022527
相关产品推荐
相关产品推荐

