PHP DOM XML转数组失败,求修正以生成指定结构数组
解决XML转指定PHP数组的问题
我来帮你搞定这个XML转PHP数组的需求!你的现有代码主要在处理空白文本节点和子元素内容合并这两部分出了问题,我们来一步步修正,实现你要的目标结构。
原代码的核心问题
- 遍历
childNodes时会包含XML里的空白文本节点(换行、缩进),导致数组出现空元素; - 处理
authors这类包含子元素的节点时,递归逻辑没有把多个同级子元素(比如多个author)合并成单个字符串,而是直接合并数组,结构不符合预期。
方案一:精准节点获取(非递归,更直观)
这个方案直接定位需要的节点,避免遍历所有子节点带来的麻烦,代码更清晰:
function arrayRepresentation(){ $xmldoc = new DOMDocument(); $xmldoc->load("data/data.xml"); $parentArray = array(); foreach ($xmldoc->getElementsByTagName('book') as $bookNode) { $bookData = []; // 获取书名 $title = $bookNode->getElementsByTagName('name')->item(0)->nodeValue; $bookData[] = trim($title); // 获取出版年份并转为整数 $year = $bookNode->getElementsByTagName('year')->item(0)->nodeValue; $bookData[] = (int)trim($year); // 收集所有作者并合并为逗号分隔的字符串 $authors = []; foreach ($bookNode->getElementsByTagName('author') as $authorNode) { $authors[] = trim($authorNode->getElementsByTagName('name')->item(0)->nodeValue); } $bookData[] = implode(', ', $authors); $parentArray[] = $bookData; } var_dump($parentArray); } arrayRepresentation();
代码说明
- 用
getElementsByTagName直接获取name、year、author节点,跳过无关的空白节点; - 作者部分先收集所有名字到数组,再用
implode合并成字符串,完美匹配需求; - 年份转为整数,和目标数组的格式一致;
- 用
trim处理所有节点值,避免前后空格干扰。
方案二:修正递归逻辑(保留原代码的递归思路)
如果你想保留递归的处理方式,我们可以修正递归函数的逻辑,解决空元素和合并问题:
function arrayRepresentation(){ $xmldoc = new DOMDocument(); $xmldoc->load("data/data.xml"); $parentArray = array(); foreach ($xmldoc->getElementsByTagName('book') as $item) { $parentArray[] = array_generate($item); } var_dump($parentArray); } function array_generate($node){ $result = []; foreach ($node->childNodes as $child) { // 跳过非元素节点(比如空白文本),避免空元素 if ($child->nodeType !== XML_ELEMENT_NODE) { continue; } if (hasChildElements($child)) { // 处理包含子元素的节点(如authors),收集子元素内容并合并 $childValues = []; foreach ($child->childNodes as $grandChild) { if ($grandChild->nodeType === XML_ELEMENT_NODE) { // 递归获取子元素的内容(author节点的name值) $childValues[] = trim(array_generate($grandChild)[0]); } } $result[] = implode(', ', $childValues); } else { // 普通元素节点,直接取修剪后的值 $result[] = trim($child->nodeValue); } } // 将年份转为整数,匹配目标格式 if (isset($result[1])) { $result[1] = (int)$result[1]; } return $result; } // 修正判断函数:只检查是否有子元素节点 function hasChildElements($node) { if ($node->hasChildNodes()) { foreach ($node->childNodes as $child) { if ($child->nodeType === XML_ELEMENT_NODE) { return true; } } } return false; } arrayRepresentation();
代码说明
- 新增判断跳过非元素节点,彻底解决空元素问题;
- 对于有子元素的节点,递归收集所有子元素的内容,再合并成字符串;
- 修正
hasChildElements函数,明确只判断是否存在子元素节点,而非所有子节点; - 最后把年份转为整数,保证格式和目标数组一致。
内容的提问来源于stack exchange,提问作者tendaitakas
相关产品推荐
相关产品推荐

