PHP Conference Japan 2024

DOMDocument::loadXML

(PHP 5, PHP 7, PHP 8)

DOMDocument::loadXML 從字串載入 XML

說明

public DOMDocument::loadXML(字串 $source, 整數 $options = 0): 布林值

從字串載入 XML 文件。

參數

source

包含 XML 的字串。

options

libxml 選項常數位元 OR

回傳值

成功時回傳 true,失敗則回傳 false

錯誤/例外

如果傳入空字串作為 source 參數,將會產生警告。此警告並非由 libxml 產生,因此無法使用 libxml 的錯誤處理函式處理。

更新日誌

版本 說明
8.3.0 此函式現在有一個暫定的 布林值 返回類型。
8.0.0 靜態呼叫此函式現在會拋出 錯誤。先前會引發 E_DEPRECATED

範例

範例 #1 建立文件

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

參見

新增註記

使用者貢獻的註記 11 則註記

46
Gustavo L. Fabro
11 年前
永遠記住,使用預設參數時,此函式無法妥善處理大型檔案,例如,如果文字節點長度超過 10MB,即使 XML 檔案格式正確,它也可能會引發指出以下訊息的例外狀況:

DOMDocument::loadXML(): internal error Extra content at the end of the document in Entity(DOMDocument::loadXML(): 內部錯誤 文件結尾有多餘內容)

即使 XML 檔案本身沒有問題。

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

要讓函式處理更大的檔案,請將 LIBXML_PARSEHUGE 作為選項傳遞,它就能正常運作

$domDocument->loadXML($xml, LIBXML_PARSEHUGE);
4
Stuart Grimshaw
17 年前
可以在這裡找到 options 參數的可能值

http://us3.php.net/manual/en/ref.libxml.php#libxml.constants
14
Gavin Sinai gsinai at gmx dot net
18 年前
當 XML 格式不正確時,loadXml 會回報錯誤,而不是拋出例外。如果您嘗試在 try...catch 陳述式中使用 loadXml(),這會很惱人。顯然這是一個特性,而不是錯誤,因為這符合規範。

如果您想要攔截例外而不是產生報告,您可以執行以下操作

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

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

?>

在 HandleXmlError() 函式中返回 false 會導致 fallback 到預設的錯誤處理器。
7
Adrian Wiik
5 年前
呼叫 loadXML() 將會覆蓋先前在 DOMDocument 建構子中建立的 XML 宣告。如果載入的 XML 中沒有 XML 宣告,而且您無法控制來源(例如,如果 XML 來自網路服務),這可能會導致編碼問題。要解決此問題,請使用 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();
?>`
由於 `nbsp` 實體已在 DOCTYPE 中定義,因此 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