PHP使用XPath操作带命名空间XML无法识别节点及修改数值问题求助
问题排查
你代码的核心错误是XPath表达式的命名空间前缀使用不完整:你仅为第一个节点MapData绑定了默认命名空间的前缀a,但该XML的默认命名空间作用于所有节点,Layouts、Layout、Dimension这些子节点同样属于该命名空间,未加前缀时XPath会默认匹配无命名空间的节点,自然无法返回结果。
修正方案
1. 正确的XPath查询写法
所有属于默认命名空间的节点都要加上绑定好的前缀,查询Dimension节点的正确写法为:
print_r($xmlDoc->xpath("//a:MapData/a:Layouts/a:Layout/a:Dimension"));
2. 完整实现单位转换功能的代码
$xmlDoc = new SimpleXMLElement($xml); // 注册所有命名空间,给无前缀的默认命名空间分配自定义前缀a foreach($xmlDoc->getDocNamespaces() as $strPrefix => $strNamespace) { if(empty($strPrefix)) { $strPrefix = "a"; } $xmlDoc->registerXPathNamespace($strPrefix, $strNamespace); } // 批量匹配所有Layout节点 $layoutList = $xmlDoc->xpath("//a:MapData/a:Layouts/a:Layout"); foreach ($layoutList as $layout) { // 修改计量单位属性为mm $layout['DefaultUnits'] = 'mm'; // 列出所有需要转换数值的子节点 $needConvert = [ $layout->xpath('./a:LowerLeft')[0], $layout->xpath('./a:DeviceSize')[0], $layout->xpath('./a:StepSize')[0] ]; foreach ($needConvert as $node) { // 微米转毫米:除以1000,保留三位小数 $node['X'] = number_format((int)$node['X'] / 1000, 3, '.', ''); $node['Y'] = number_format((int)$node['Y'] / 1000, 3, '.', ''); } } // 输出修改后的XML内容 $modifiedXml = $xmlDoc->asXML(); echo $modifiedXml;
额外说明
如果需要输出格式化缩进的XML内容,可以将SimpleXMLElement对象导入DOMDocument后处理:
$dom = new DOMDocument('1.0'); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; $dom->loadXML($xmlDoc->asXML()); echo $dom->saveXML();
内容的提问来源于stack exchange,提问作者Stefano Radaelli
相关产品推荐
相关产品推荐

