在PHP后端开发中,经常需要把业务数据输出成XML格式供第三方系统对接,或者读取外部传来的XML报文。PHP标准库中的DOMDocument类提供了一套面向对象的节点操作接口,能够完成XML的创建、修改与解析。它不依赖任何扩展编译参数,只要PHP装了dom扩展即可使用,是处理XML最基础也最可靠的工具之一。
使用DOMDocument生成XML文档
生成XML的核心思路是先创建DOMDocument对象,再通过createElement、appendChild等方法逐步搭建节点树,最后用saveXML或save输出。在实例化时可以传入版本号和编码,这样生成的XML会自动带上声明头,避免下游解析时因缺少encoding而误判字符集。
下面的示例演示如何把一个简单的订单数组转为XML。注意文本节点要用createTextNode写入,DOMDocument会自动把&、<等特殊字符转义,不需要开发者手动处理。如果直接把字符串拼进createElement第二个参数,在某些版本里也能转义,但分开写文本节点语义更清晰。
<?php
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$root = $dom->createElement('order');
$dom->appendChild($root);
$idNode = $dom->createElement('id');
$idNode->appendChild($dom->createTextNode('1001'));
$root->appendChild($idNode);
$nameNode = $dom->createElement('product');
$nameNode->appendChild($dom->createTextNode('键盘 & 鼠标'));
$root->appendChild($nameNode);
echo $dom->saveXML();
?>
上述代码运行后会输出带缩进的XML,其中“键盘 & 鼠标”中的&被正确转义为&。如果设置formatOutput为false,则输出紧凑单行文本,适合网络传输。相比用simplexml方式,DOMDocument在需要插入注释、处理命名空间、复制节点等复杂操作时更灵活。
另外,如果要在节点上添加属性,可以使用setAttribute方法。属性值同样会被自动转义。当数据结构嵌套较深时,建议写成递归函数,每遇到一个子数组就创建一个父节点并把子项挂上去,这样能避免大量重复的appendChild调用使代码难以维护。
用DOMDocument解析已有XML
解析XML时,最常见的是从文件或字符串载入。DOMDocument提供了load和loadXML两个方法,前者读取外部文件,后者解析字符串。载入后可通过getElementsByTagName按标签名获取节点列表,也可以用DOMXPath写路径表达式查询。需要注意load默认不会抛出异常,而是通过返回值false表示失败,因此要手动判断。
下面代码展示如何解析一段XML并取出所有商品名。节点列表是类数组结构,可用foreach遍历,每个元素是DOMElement对象,用nodeValue取文本。若节点不存在,getElementsByTagName返回空列表,不会报错,但取属性时要先确认hasAttribute,否则getAttribute返回空串容易误导业务逻辑。
<?php
$xml = '<shop><item>手机</item><item>平板</item></shop>';
$dom = new DOMDocument();
if (!$dom->loadXML($xml, LIBXML_NOERROR)) {
die('XML解析失败');
}
$items = $dom->getElementsByTagName('item');
foreach ($items as $node) {
echo $node->nodeValue . "n";
}
?>
对于结构复杂的报文,推荐配合XPath使用。先new DOMXPath($dom),再调用query方法传入如//order/item[@type="gift"]这样的表达式,能精准定位带属性的深层节点。XPath的返回值也是DOMNodeList,遍历方式和上面一致。这种方式比一层层childNodes判断要简洁很多,也更容易应对对方接口字段顺序变化。
解析时另一个坑是编码。如果XML声明里写了encoding="GBK",而PHP文件本身是UTF-8,直接nodeValue取出可能出现乱码。此时应在载入前用mb_convert_encoding把字符串转成和DOMDocument内部一致的编码,或者在输出时统一转码,保证两端字符集对齐。
常见错误与性能注意事项
新手常犯的一个错误是混淆标签名和函数调用。比如在正文里讨论HTML的<input>元素时要转义写成<input>,但写PHP代码里的DOMDocument->load()是方法调用,不能写成<load>这种标签形式。还有人把code标签当成普通文字转义,导致页面显示出尖括号而非高亮,正确做法是用来做行内代码展示,而标签名本身在讨论时才转义。示例
在生成超大XML时,DOMDocument会把整棵树放在内存里,数据量到几十万节点可能占用上百兆内存。如果接口只是单向导出且不需回读,可考虑XMLWriter流式写入;但若既要生成又要局部修改,DOMDocument的节点操作便利性仍难以替代。解析端同理,超大文件用XMLReader逐节点拉取更省内存,小文件用DOMDocument写起来最快。
最后提醒,使用save方法写文件时要确认目录有写权限,且不要信任外部传入的文件名,避免路径遍历。解析不可信XML时建议加上LIBXML_NONET参数禁止加载外部实体,防止XXE注入风险。只要注意这些点,DOMDocument足以覆盖绝大多数PHP项目里的XML生成与解析需求。
PHPDOMDocumentXML修改时间:2026-08-15 15:24:36