PHP SimpleXML生成XML时如何移除子元素多余命名空间声明
问题根源
SimpleXML的addChild方法第三个参数接收的是待添加元素所属的命名空间完整URI,不是命名空间前缀。你之前调用时要么传了节点本地名(比如id/type)、要么传空字符串,会让SimpleXML认为你需要在当前节点重新声明对应前缀的命名空间,最终生成冗余的xmlns:g属性。
解决方案
在根节点声明好g前缀对应的命名空间后,后续所有带g:前缀的子节点调用addChild时,第三个参数传入和根节点声明完全一致的命名空间URI即可。SimpleXML识别到该命名空间已经在父级绑定了对应前缀,就不会重复生成命名空间声明。
可直接运行的正确代码示例
<?php // 初始化XML根节点,提前声明需要用到的命名空间 $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss xmlns:g="http://base.google.com/ns/1.0" xmlns:c="http://base.google.com/cns/1.0" version="2.0"></rss>'); $channel = $xml->addChild('channel'); $channel->addChild('title', 'MY XML'); $item = $channel->addChild('item'); // 定义g前缀对应的命名空间常量,后续添加g前缀节点时统一传入 $googleMerchantNs = 'http://base.google.com/ns/1.0'; $item->addChild('g:id', '123', $googleMerchantNs); $item->addChild('title', 'abc'); $item->addChild('g:type', 'vertical', $googleMerchantNs); $item->addChild('g:price', '0.00', $googleMerchantNs); // 如需输出格式化缩进的XML,可配合DOMDocument处理 $dom = new DOMDocument('1.0', 'utf-8'); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; $dom->loadXML($xml->asXML()); echo $dom->saveXML();
注意事项
- 不要给
addChild第三个参数传命名空间前缀、节点本地名或者空字符串,否则一定会触发重复命名空间声明的问题。 - SimpleXML本身没有内置格式化输出的配置,需要缩进排版的话直接用上面示例里的DOMDocument转换方法即可,不会修改原有XML结构。
内容的提问来源于stack exchange,提问作者Daniel Newton
相关产品推荐
相关产品推荐

