PHP中带属性的嵌套XML转换为多维数组的递归处理问题
PHP中带属性的嵌套XML转换为多维数组的递归处理问题
看起来你已经迈出了不错的第一步,但确实遇到了递归处理嵌套节点的问题——你的当前函数只处理了顶层的XML元素,没有深入解析子节点(比如第二个item里的subb元素),而且重复节点的处理逻辑也有点小问题。我来帮你调整一下函数,让它能递归处理所有层级,同时正确处理重复节点的数组结构。
首先明确核心需求:
- 把XML的属性转为数组元素(比如统一用
@attributes键存储) - 节点的文本值存为
@value - 嵌套的子节点也要按同样规则递归转换
- 同名的重复节点自动转为数组形式,单个节点则保持为键值对
那我们来修改xmlToArray函数,完善递归逻辑和重复节点处理:
$xmlString = '<root><item id="1" name="ItemOne">Item Value 1</item><item id="2" name="ItemTwo"><subb>Sub Value 1</subb><subb>Sub Value 2</subb></item><item id="3" name="ItemThree">Value 3</item><something>something value</something></root>'; function xmlToArray($xmlNode) { $array = []; // 处理当前节点的属性 $attributes = (array)$xmlNode->attributes(); if (!empty($attributes)) { $array['@attributes'] = array_map('trim', (array)$attributes['@attributes']); } // 处理当前节点的文本值 $textValue = trim((string)$xmlNode); if (!empty($textValue)) { $array['@value'] = $textValue; } // 递归处理所有子节点 foreach ($xmlNode->children() as $childNode) { $childArray = xmlToArray($childNode); $childKey = (string)$childNode->getName(); // 处理重复节点:如果键已存在,自动转为数组格式 if (isset($array[$childKey])) { // 若当前值不是数组,先把已有值包装成数组 if (!is_array($array[$childKey]) || !isset($array[$childKey][0])) { $array[$childKey] = [$array[$childKey]]; } $array[$childKey][] = $childArray; } else { $array[$childKey] = $childArray; } } // 优化:如果节点只有文本值,直接返回文本(可选,根据需求调整) if (empty($array['@attributes']) && count($array) === 1 && isset($array['@value'])) { return $array['@value']; } return $array; } // 加载XML并执行转换 $xmlObject = simplexml_load_string($xmlString); $resultArray = xmlToArray($xmlObject); // 打印结果查看结构 echo '<pre>'.print_r($resultArray, true).'</pre>';
代码关键说明:
- 递归解析:函数会调用自身处理每个子节点,不管XML嵌套多少层,都能逐层解析成对应结构的数组。
- 属性与文本分离:用
@attributes统一存储节点属性,@value存储文本值,结构更清晰规范。 - 重复节点处理:遇到同名节点时,自动将已有值转为数组并追加新节点数据,避免覆盖问题。
- 轻量优化:对于只有文本值的节点,直接返回文本而非嵌套数组,让结果更简洁(不需要的话可以删掉这个判断)。
运行后你会得到符合预期的多维数组,其中第二个item里的两个subb节点会被正确转为数组:
Array ( [item] => Array ( [0] => Array ( [@attributes] => Array ( [id] => 1 [name] => ItemOne ) [@value] => Item Value 1 ) [1] => Array ( [@attributes] => Array ( [id] => 2 [name] => ItemTwo ) [subb] => Array ( [0] => Sub Value 1 [1] => Sub Value 2 ) ) [2] => Array ( [@attributes] => Array ( [id] => 3 [name] => ItemThree ) [@value] => Value 3 ) ) [something] => something value )
内容来源于stack exchange
相关产品推荐
相关产品推荐

