PHP Conference Japan 2024

DOMDocument::loadXML

(PHP 5, PHP 7, PHP 8)

DOMDocument::loadXML 从字符串加载 XML

描述

public DOMDocument::loadXML(string $source, int $options = 0): bool

从字符串加载 XML 文档。

参数

source

包含 XML 的字符串。

options

按位 OR libxml 选项常量

返回值

成功返回 true,失败返回 false

错误/异常

如果将空字符串作为 source 传递,则会生成警告。此警告不是由 libxml 生成,无法使用 libxml 的错误处理函数进行处理。

变更日志

版本 描述
8.3.0 此函数现在具有暂定的 bool 返回类型。
8.0.0 静态调用此函数现在将抛出 Error 异常。以前,会引发 E_DEPRECATED

示例

示例 #1 创建文档

<?php
$doc
= new DOMDocument();
$doc->loadXML('<root><node/></root>');
echo
$doc->saveXML();
?>

参见

添加注释

用户贡献的注释 11 条注释

46
Gustavo L. Fabro
11 年前
始终记住,使用默认参数,此函数无法很好地处理大型文件,即,如果文本节点长度超过 10MB,它可能会引发异常,指出

DOMDocument::loadXML(): internal error Extra content at the end of the document in Entity

即使 XML 很好。

原因是 lixml 中 parserInternals.h 的定义
#define XML_MAX_TEXT_LENGTH 10000000

要允许函数处理更大的文件,请将 LIBXML_PARSEHUGE 作为选项传递,它将正常工作

$domDocument->loadXML($xml, LIBXML_PARSEHUGE);
4
Stuart Grimshaw
17 年前
选项参数的可能值可以在这里找到

http://us3.php.net/manual/en/ref.libxml.php#libxml.constants
14
Gavin Sinai gsinai at gmx dot net
18 年前
当 XML 格式不正确时,loadXml 报告错误而不是抛出异常。如果您尝试在 try...catch 语句中加载 Xml(),这会很烦人。显然这是一个特性,而不是一个错误,因为这符合规范。

如果您想捕获异常而不是生成报告,您可以执行以下操作

<?php
function HandleXmlError($errno, $errstr, $errfile, $errline)
{
if (
$errno==E_WARNING && (substr_count($errstr,"DOMDocument::loadXML()")>0))
{
throw new
DOMException($errstr);
}
else
return
false;
}

function
XmlLoader($strXml)
{
set_error_handler('HandleXmlError');
$dom = new DOMDocument();
$dom->loadXml($strXml);
restore_error_handler();
return
$dom;
}

?>

在函数 HandleXmlError() 中返回 false 会导致回退到默认错误处理程序。
7
Adrian Wiik
5 年前
对 loadXML() 的调用将覆盖先前在 DOMDocument 构造函数中创建的 XML 声明。如果加载的 XML 中没有 XML 声明并且您无法控制源(例如,如果 XML 来自 Web 服务),这可能会导致编码问题。要解决此问题,请使用 DOMDocument 的“encoding”类属性在加载 XML 后设置编码。示例

糟糕的情况

test.xml
<test>
<hello>hi</hello>
<field>ø</field>
</test>

test.php
$xmlDoc = new DOMDocument("1.0", "utf-8"); // 使用 loadXML() 时,此处参数无论如何都会被覆盖,并且实际上并不相关
$testXML = file_get_contents("test.xml");
$xmlDoc->loadXML($testXML);
// 使用 $xmlDoc->saveXML() 将内容打印到文件或日志函数以获取输出

输出
<?xml version="1.0"?>
<test>
<hello>hi</hello>
<field>&#xF8;</field>
</test>

好的情况

test.xml
<test>
<hello>hi</hello>
<field>ø</field>
</test>

test.php
$xmlDoc = new DOMDocument("1.0", "utf-8"); // 使用 loadXML() 时,此处参数无论如何都会被覆盖,并且实际上并不相关
$testXML = file_get_contents("test.xml");
$xmlDoc->loadXML($testXML);
$xmlDoc->encoding = "utf-8";
// 使用 $xmlDoc->saveXML() 将内容打印到文件或日志函数以获取输出

输出
<?xml version="1.0" encoding="utf-8"?>
<test>
<hello>hi</hello>
<field>ø</field>
</test>
6
shaoyu73 at gmail dot com
17 年前
earth at anonymous dot com,

出于某种原因,需要将 preserveWhiteSpace 属性设置为 false 才能使 formatOutput 正确工作。

$dom = new DOMDocument;
$dom->preserveWhiteSpace = false;
$dom->loadXML($xmlStr);
...
$element->appendChild(...);
...
$dom->formatOutput = true;
$xmlStr = $dom->saveXML();
echo $xmlStr;

这将很好地格式化输出。
2
Marc Liyanage
17 年前
文档说明 loadXML 可以静态调用,但这具有误导性。根据 http://bugs.php.net/bug.php?id=41398.,此功能似乎是一个特殊情况的 hack,并且似乎不鼓励使用它。

如果代码在启用 E_STRICT 错误报告的情况下运行,则静态调用该方法将失败并出现错误。

文档应该更改,以明确静态调用违反了推荐的实践,并且在 E_STRICT 下无法工作。
2
earth at anonymous dot com
18 年前
请注意,loadXML 会裁剪开头和结尾的空格和换行符。

使用 loadXML 和 appendChild 将 XML 块添加到现有文档时,您可能希望在 XML 块的末尾和输出文件中的下一行(通常是结束标签)之间强制换行

$childDocument = new DOMDocument;
$childDocument>preserveWhiteSpace = true;
$childDocument->loadXML(..XML-Chunk..);
$mNewNode = $mainDOcument->importNode($childDocument->documentElement, true);
$ParentNode->appendChild($mNewNode);
$ParentNode->appendChild($mainDocument->createTextNode("\\n "));

虽然据说不应该使用DOM来创建“漂亮”的XML输出,但这正是我为获得可读的测试结果而努力解决的问题。另一种解决方案是使用createDocumentFragment()->appendXML(..XML-Chunk..)代替,它似乎不会像DOMDocument->loadXML()那样去除换行符。
3
olalonde at NOSPAM dot gmail dot com
16年前
出于某种原因,当您将DOMDocument的属性“recover”设置为true时,使用“@”来屏蔽loadXml()抛出的错误将无效。

这是我的解决方法

function maskErrors() {}
set_error_handler('maskErrors');
$dom->loadXml($xml);
restore_error_handler();

您也可以简单地执行此操作:error_reporting(0); 然后将error_reporting设置回其原始状态。
3
jazzslider at hotmail dot com
17 年前
当使用loadXML()解析包含实体引用(例如,&nbsp;)的字符串时,请确保通过使用DOCTYPE声明正确声明这些实体引用;否则,loadXML()将无法解释该字符串。

示例
<?php
$str
= <<<XML
<?xml version="1.0" encoding="iso-8859-1"?>
<div>This&nbsp;is a non-breaking space.</div>
XML;

$dd1 = new DOMDocument();
$dd1->loadXML($str);

echo
$dd1->saveXML();
?>

鉴于以上代码,PHP将发出关于未正确声明实体“nbsp”的警告。此外,对saveXML()的调用将只返回原始处理指令的简化版本……其他所有内容都消失了,这一切都是因为未声明的实体。

相反,首先显式声明实体
<?php
$str
= <<<XML
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE root [
<!ENTITY nbsp "&#160;">
]>
<div>This&nbsp;is a non-breaking space.</div>
XML;

$dd2 = new DOMDocument();
$dd2->loadXML($str);

echo
$dd2->saveXML();
?>

由于在DOCTYPE中定义了“nbsp”实体,PHP不再发出该警告;该字符串现在格式良好,loadXML()可以完美地理解它。

您也可以以相同的方式使用对外部DTD的引用(例如,<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">),如果您需要对许多具有许多不同可能实体的不同文档执行此操作,这一点尤其重要。

另外,顺便提一句……由createEntityReference()创建的实体引用不需要这种显式声明。
2
remacg
15年前
不要这样做

<?php
$str
= <<<XML
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE root [
<!ENTITY nbsp "&#160;">
]>
<div>This&nbsp;is a non-breaking space.</div>
XML;

$dd2 = new DOMDocument();
$dd2->loadXML($str);

echo
$dd2->saveXML();
?>

只需使用

loadHTML() 而不是 loadXML()。
2
mp at webfactory dot de
18 年前
虽然loadXML()期望其输入具有领先的XML处理指令来推断使用的编码,但在(非XML)HTML文档中没有这样的概念。因此,DOM函数底层的libxml库会查看<META>标签以确定使用的编码。

参见 http://xmlsoft.org/encoding.html.
To Top