PHP使用simplexml_load_string解析XML返回空数组问题排查
问题原因
解析返回空数组是三个问题叠加导致的:
- XML根节点
<DataSet>声明了默认命名空间xmlns="http://tempuri.org/Prices_Feed/Service1",SimpleXML不会自动识别默认命名空间下的子节点,直接转JSON时这类节点会被识别为空值。 - 代码虽然开启了
libxml_use_internal_errors(TRUE),但没有配套的错误捕获逻辑,解析时的命名空间匹配错误被静默吞掉,没有任何报错提示。 - 实际业务数据存放在
diffgr:diffgram节点下的<Ticker>块里,外层的xs:schema只是XML结构定义,不存储实际业务数据,原有写法没有定位到正确的数据节点,直接对整个根节点转码自然拿不到有效内容。
可行解决方案
放弃加载XML后直接无脑转JSON的写法,先注册对应命名空间,定位到实际存储数据的diffgram节点再做转码处理,修正后的可运行代码如下:
<?php libxml_use_internal_errors(TRUE); $xml = file_get_contents("https://egytech4uu.herokuapp.com/data.xml"); $XML = simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA); // 注册根节点默认命名空间 $XML->registerXPathNamespace('default', 'http://tempuri.org/Prices_Feed/Service1'); // 注册diffgr命名空间,用于定位数据块 $XML->registerXPathNamespace('diffgr', 'urn:schemas-microsoft-com:xml-diffgram-v1'); // 通过XPath直接定位到存储实际数据的diffgram节点 $diffgram = $XML->xpath('//default:diffgr:diffgram'); $dataNode = $diffgram[0]->children()[0]; // 取出diffgram下的Ticker数据根节点 // 转数组输出 $json = json_encode($dataNode); $arr = json_decode($json,TRUE); print_r($arr); // 排查解析错误时可取消下方注释 // foreach(libxml_get_errors() as $error) { // var_dump($error); // } ?>
补充说明
- 上述代码运行后可以正常拿到数据更新时间、所有股票的代码、中英文名称、开盘价、收盘价信息,不会再返回空数组。
- 后续如果XML结构调整,只需要修改XPath定位路径即可,不要直接对整个XML根节点做JSON编码,外层的schema定义、命名空间声明节点都会干扰转码结果。
- 如果不需要保留XML结构定义信息,也可以在加载XML后先移除
xs:schema节点再做后续处理,减少无效节点的干扰。
内容的提问来源于stack exchange,提问作者Abdulrahman Mohamed
相关产品推荐
相关产品推荐

