PHP使用simplexml读取XML节点无返回值的问题排查
问题场景
现有如下XML文件somefile.xml:
<string xmlns="http://tempuri.org/"> <SomeDataSet> <someData> <a>AAAA</a> <b>BBBB</b> <c>CCCC</c> <d>DDDD</d> </someData> </SomeDataSet> </string>
尝试用如下SimpleXML代码获取c节点的取值CCCC,但所有路径访问都返回空:
$xml = simplexml_load_file("somefile.xml"); var_dump($xml); // 能返回完整的SimpleXMLElement对象 var_dump($xml->someData->SomeDataSet); // 无返回值 var_dump($xml->SomeDataSet->someData->c); // 无返回值 var_dump($xml->someData->c); // 无返回值 var_dump($xml->someData); // 无返回值 var_dump($xml->c); // 无返回值
问题根源
访问失败有两个核心原因:
- 默认命名空间未做处理:XML根节点声明了默认命名空间
xmlns="http://tempuri.org/",所有子节点默认都属于这个命名空间。SimpleXML不会将命名空间下的节点直接挂载到对象公开属性上,直接用无命名空间的节点名访问必然拿不到结果。 - 节点层级顺序写反:根节点
<string>的直接子节点是<SomeDataSet>,<someData>是<SomeDataSet>的子节点,代码中$xml->someData->SomeDataSet的写法完全颠倒了父子层级关系,哪怕没有命名空间,这个路径也无法命中目标节点。
修复方案
方案1:通过children()方法指定命名空间访问
调用children()方法传入对应命名空间的URI,拿到该命名空间下的节点集合后,按正确层级访问即可。注意要主动做字符串强转才能拿到节点的文本内容,否则拿到的是SimpleXMLElement对象:
$xml = simplexml_load_file("somefile.xml"); // 获取指定命名空间下的节点 $ns = $xml->children('http://tempuri.org/'); // 按正确层级访问目标节点 var_dump((string)$ns->SomeDataSet->someData->c); // 输出string(4) "CCCC"
方案2:注册命名空间前缀后用XPath查询
如果需要灵活定位多层级节点,可以先给默认命名空间注册一个别名前缀,再通过XPath语法查询:
$xml = simplexml_load_file("somefile.xml"); // 为默认命名空间注册前缀temp $xml->registerXPathNamespace('temp', 'http://tempuri.org/'); // XPath查询目标c节点 $res = $xml->xpath('//temp:c'); var_dump((string)$res[0]); // 输出string(4) "CCCC"
内容的提问来源于stack exchange,提问作者AndrewL64
相关产品推荐
相关产品推荐

