我花了很长时间才发现
DOMDocument->formatOutput = true
只有在也设置了以下内容时,才能对从磁盘加载的文档产生影响:
DOMDocument->preserveWhiteSpace = false ....
希望这能帮其他人避免头痛。
(PHP 5, PHP 7, PHP 8)
DOMDocument::save — 将内部 XML 树转储回文件
从 DOM 表示创建 XML 文档。此函数通常在从头开始构建新的 dom 文档后调用,如下例所示。
返回写入的字节数或false
(如果发生错误)。
示例 #1 将 DOM 树保存到文件
<?php
$doc = new DOMDocument('1.0');
// 我们想要一个漂亮的输出
$doc->formatOutput = true;
$root = $doc->createElement('book');
$root = $doc->appendChild($root);
$title = $doc->createElement('title');
$title = $root->appendChild($title);
$text = $doc->createTextNode('This is the title');
$text = $title->appendChild($text);
echo 'Wrote: ' . $doc->save("/tmp/test.xml") . ' bytes'; // Wrote: 72 bytes
?>
我花了很长时间才发现
DOMDocument->formatOutput = true
只有在也设置了以下内容时,才能对从磁盘加载的文档产生影响:
DOMDocument->preserveWhiteSpace = false ....
希望这能帮其他人避免头痛。
XML 解析器会将 XML 文档的文本转换为 UTF-8,即使您已设置 XML 的字符编码(例如,作为 DOMDocument 构造函数的第二个参数)。使用 load() 命令解析 XML 后,其所有文本都已转换为 UTF-8。
如果您将带有特殊字符(例如变音符号)的文本节点附加到 XML 文档,则应在将文本附加到文档之前,使用 utf8_encode() 将其转换为 UTF-8。否则,在 save() 命令处会收到类似“由于转换错误导致输出转换失败”的错误消息。请参见下面的示例
<?php
// 要插入到下面 XML 的文本
$txt = "a text with special characters like 'ä', 'ß', 'Ü' etc.";
// 创建 DOMDocument 实例
$dom = new DOMDocument;
// 加载 XML 文件
// 之前使用 DOMDocument('1.0', 'iso-8859-1') 创建
$dom = $dom->load("file.xml");
// 查找父节点
$parent = $dom->documentElement;
// 创建 DomXPath 实例
$xpath = new DomXPath($dom);
// 将在该节点之前插入新节点
$next = $xpath->query("//parentnode/childnode");
// 创建新元素
$new_elem = $dom->createElement('new_elem');
// 插入新元素
$parent->insertBefore($new_elem, $next->item(0));
// DOMXML = utf-8!(仅在 'save()' 时转换为 iso-8859-1)
// 可防止在 'save()' 时出现错误消息“由于转换错误导致输出转换失败”
$txt = utf8_encode($txt);
// 使用 utf-8 编码的字符串创建新的文本节点
$nodetext = $dom->createTextNode("$txt");
// 将文本节点附加到新元素
$nodetext = $new_elem->appendChild($nodetext);
// 保存
$dom->save("file.xml");
?>
希望这对某些人有所帮助。
siegparr
我只是想为结合使用 DOMDocument::save() 函数和 PHP serialize() 函数贡献一点微薄之力。
有时您可能需要在将 PHP 对象放入 XML 结构(或其他结构)之前对其进行序列化。然后,我想您可能需要将此 XML 结构保存到文件中。当然,您还需要进一步读取此文件并在使用其内容之前对其进行反序列化。
当要序列化的对象中存在一些被声明为受保护的属性时,问题就会出现。
正如 PHP 文档中所写,serialize 函数会在这些受保护属性的名称前添加一个星号,并在星号的两侧各添加一个 NULL 字符。
在这种情况下,由于PHP认为空字符(NULL)存在潜在风险,`DOMDocument::save` 函数会在遇到第一个空字符时停止保存操作。
因此,之后文件的反序列化操作将变得不可能。
为了解决这个问题,这里提供第一个解决方案:
对于序列化,在 `DOMDocument::save()` 之前:
$data_serial = explode("\x00\x2A\x00", serialize($object)); // 去除 'NULL * NULL' 字符串
$data_serial = implode("\x5C\x30\x2A\x5C\x30", $data_serial); // 并替换为 '\0*\0' 字符串
反序列化之前:
$data_serial = explode("\x5C\x30\x2A\x5C\x30", $serialized_object); // 去除 '\0*\0' 字符串
$serial_object = implode("\x00\x2A\x00", $data_serial); // 并替换为 'NULL * NULL' 字符串,与之前的序列化保持一致
第二个解决方案:
对于序列化,在 `DOMDocument::save()` 之前:
$serialized_object = addslashes(serialize($object));
在应用程序中重新使用对象之前:
$object = unserialize(stripslashes($serialized_object));
希望这对某些人有所帮助。
从头创建 DOMDocument 并保存时,即使声明为 iso-8859-1,编码也将为 utf-8。
加载声明并保存为 iso-8859-1 的 XML 文件时,在进行更改后保存时,php 将保留正确的编码。
Php 内部将声明为 iso-8859-1 的文件转换为 utf-8。要添加包含特殊字符的文本,文本必须编码为 utf-8。保存文档时,特殊字符将转换为 iso-8859-1。
要保存从头创建的 xml,请使用 fopen/fwrite 和 utf8_decode
$doc = new DOMDocument('1.0', 'iso-8859-1');
//添加一些节点和文本,使用适当的方法
$f = fopen('xmlfile.xml', 'w+');
fwrite($f, utf8_decode($doc->saveXML()));
fclose($f);
当我无法保存已编辑的 XML 文件(由于文件权限问题)时,我一直在碰壁,即使我知道权限没问题。
最终我意识到,由于某些奇怪的原因,当我保存 XML 文件时,它会尝试将文件写入根目录。
因此,在加载 XML 文件时,请使用 `realpath()` 来保留 XML 文件的完整系统路径
<?php
$myfile = 'myxml.xml';
$myfile = realpath($myfile);
$doc = new DOMDocument('1.0');
$doc->load($myfile);
// 为了保险起见,我们添加几个元素
$root = $doc->documentElement;
$title = $doc->createElement('title');
$title = $root->appendChild($title);
$text = $doc->createTextNode('This is a title');
$text = $title->appendChild($text);
$doc->save($myfile);
?>