创建 SimpleXMLElement 根节点须传合法 XML 字符串如 <data/>,禁用空字符串或 null;添加子节点用 addChild() 并链式调用 addAttribute();保存前需 asXML() 校验再 file_put_contents。

用 SimpleXMLElement 创建根节点时,别直接 new 一个空对象
很多人一上来就写 new SimpleXMLElement(''),结果报错 String could not be parsed as XML。这是因为构造函数要求传入的是合法的 XML 字符串(哪怕只是 <root/>),不是空字符串或 null。
正确做法是提供最简 XML 结构:
$xml = new SimpleXMLElement('<data/>');
或者更稳妥地带上 XML 声明(尤其要输出文件时):
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><data/>');
- 如果后续要添加中文内容,
encoding="UTF-8"必须显式声明,否则asXML()输出可能乱码 - 不要用
new SimpleXMLElement(null)或new SimpleXMLElement([])—— 都会失败 - 构造后立即调用
asXML()测试是否可序列化,能避免后续追查节点不生效的问题
向 SimpleXMLElement 添加子节点:用 addChild() 而非数组赋值
常见误区是把 $xml->item = 'value' 当作“创建节点”,这其实只是设置已有节点的文本内容;若 item 不存在,PHP 会静默创建,但行为不可靠(比如嵌套结构易出错、属性无法同时设置)。
立即学习“PHP免费学习笔记(深入)”;
真正可控的方式是明确调用 addChild():
$item = $xml->addChild('item', 'apple');<br>$item->addAttribute('id', '1');
-
addChild($name, $value)返回新创建的节点对象,方便链式添加属性或子节点 - 若值含特殊字符(如
<、&),addChild()会自动转义;手动拼接字符串再赋值容易漏转义,导致 XML 格式损坏 - 重复调用
addChild('item')会生成多个同名兄弟节点,符合预期;而$xml->item = ...每次都会覆盖前一个
给节点添加属性必须用 addAttribute(),不能用箭头赋值
写 $xml->item['type'] = 'fruit' 看似直观,但这是非法操作 —— SimpleXMLElement 对象不支持通过数组语法设置属性,运行时会报 Cannot use object of type SimpleXMLElement as array。
唯一正确方式是调用 addAttribute():
$item = $xml->addChild('item', 'apple');<br>$item->addAttribute('type', 'fruit');<br>$item->addAttribute('unit', 'kg');
- 属性名和属性值都会被自动 XML 转义,无需手动处理引号或
& - 同一个节点多次调用
addAttribute()不会覆盖,而是累加不同属性 - 如果需要动态键名(如变量
$attrName),必须用$node->addAttribute($attrName, $value),不能硬编码方括号
保存为文件前记得用 asXML() 并检查返回值
SimpleXMLElement 本身不提供 save() 方法,必须先转成字符串再写入文件。直接 file_put_contents('out.xml', $xml) 是错的 —— $xml 是对象,不是字符串。
正确流程是:
$output = $xml->asXML();<br>if ($output === false) {<br> throw new RuntimeException('XML generation failed');<br>}<br>file_put_contents('data.xml', $output);
-
asXML()失败时返回false(比如内部节点结构异常),不检查就写入会导致空文件 - 如果想压缩输出(去掉缩进),传入参数
asXML('data.xml')可直接保存,但依然建议先捕获返回值做校验 - 注意文件路径权限:Web 进程用户(如 www-data)需对目标目录有写权限,否则静默失败
嵌套层级深、含 CDATA 或命名空间时,SimpleXMLElement 的行为会变复杂,这时候别硬扛,优先考虑用 DOMDocument 替代。



















