PHP:带命名空间的SimpleXML转JSON返回空结果问题
解决带命名空间的SimpleXML转JSON返回空的问题
这个坑我之前踩过!当你用json_encode直接序列化带命名空间的SimpleXML对象时,确实会出现返回空JSON的情况,原因是SimpleXML对命名空间节点的处理比较特殊,默认情况下json_encode没法正确识别和序列化这些带前缀的元素。
问题根源
SimpleXML中,带命名空间的节点(比如soapenv:Envelope、ser:processTrans)不会被默认的遍历逻辑包含进去,你必须显式指定命名空间才能访问这些节点。而json_encode在处理SimpleXML对象时,只会序列化那些能被默认遍历到的内容,所以自然就返回空或者不完整的结果了。
解决方案:先转成普通PHP数组再转JSON
我们可以写一个递归函数,把带命名空间的SimpleXML对象完整转换成普通PHP数组,这样json_encode就能正常处理了。这个函数会处理:
- 节点的属性
- 命名空间下的子节点
- 普通子节点
- 节点的文本内容
下面是完整的代码示例:
function simplexmlToArray($xml) { $result = []; // 提取节点属性 foreach ($xml->attributes() as $attrName => $attrValue) { $result['@attributes'][(string)$attrName] = (string)$attrValue; } // 处理所有命名空间下的子节点 foreach ($xml->getNamespaces(true) as $prefix => $namespace) { foreach ($xml->children($namespace) as $childName => $childNode) { $childData = simplexmlToArray($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; } } } // 处理普通命名空间的子节点 foreach ($xml->children() as $childName => $childNode) { $childData = simplexmlToArray($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 ($textContent !== '') { $result['@value'] = $textContent; } // 简化结构:如果只有文本内容,直接返回文本;如果只有文本+属性,合并返回 if (count($result) === 1 && isset($result['@value'])) { return $result['@value']; } elseif (count($result) === 2 && isset($result['@attributes']) && isset($result['@value'])) { $temp = $result['@attributes']; $temp['@value'] = $result['@value']; return $temp; } return $result; } // 你的带命名空间的XML字符串 $xmlstr = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header /> <soapenv:Body> <ser:processTrans> <xmlValue> <ebpacket> <head> <packettype> UserAuthorization</packettype> <staffcode> UserName </staffcode> <pwd> Password </pwd> <env> Evnironment </env> </head> </ebpacket> </xmlValue> </ser:processTrans> </soapenv:Body> </soapenv:Envelope>'; // 预处理XML字符串(可选,去除换行) $xml_str = str_replace(PHP_EOL, '', $xmlstr); // 加载XML为SimpleXML对象 $xml = simplexml_load_string($xml_str, 'SimpleXMLElement', LIBXML_NOCDATA); // 先转成普通数组 $xmlArray = simplexmlToArray($xml); // 再转成格式化后的JSON $json_object = json_encode($xmlArray, JSON_PRETTY_PRINT); // 输出结果 echo $json_object;
代码说明
simplexmlToArray函数会递归遍历整个SimpleXML结构,把所有节点(包括命名空间节点)、属性、文本内容都转换成PHP数组的形式。- 针对同名节点的情况,函数会自动把它们转换成数组,避免覆盖。
- 最后对只有文本或文本+属性的节点做了结构简化,让JSON结果更简洁。
这样处理后,你就能得到完整的JSON结果,再也不会返回空了!
内容的提问来源于stack exchange,提问作者Dilani
相关产品推荐
相关产品推荐

