PHP Conference Japan 2024

DOMDocument::load

(PHP 5, PHP 7, PHP 8)

DOMDocument::load 從檔案載入 XML

描述

public DOMDocument::load(string $filename, int $options = 0): bool

從檔案載入 XML 文件。

警告

使用斜線的 Unix 風格路徑可能會導致 Windows 系統上效能大幅降低;在這種情況下,請務必呼叫 realpath()

參數

filename

XML 文件的路徑。

options

位元 ORlibxml 選項常數

回傳值

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

錯誤/例外

如果將空字串作為 filename 傳遞,或指定空的檔案,將會產生警告。這個警告不是由 libxml 產生,無法使用 libxml 的錯誤處理函式處理。

變更記錄

版本 描述
8.3.0 這個函式現在有一個暫定的 bool 回傳型別。
8.0.0 靜態呼叫此函式現在會擲出 Error。先前會引發 E_DEPRECATED

範例

範例 #1 建立文件

<?php
$doc
= new DOMDocument();
$doc->load('book.xml');
echo
$doc->saveXML();
?>

參見

新增註解

使用者貢獻的註解 14 則註解

15
Jonas Due Vesterheden
15 年前
我在透過 HTTP 載入文件時遇到問題。我會收到類似這樣的錯誤

警告:DOMDocument::load(http://external/document.xml):無法開啟串流:HTTP 請求失敗!HTTP/1.1 500 內部伺服器錯誤

該文件在瀏覽器和使用 wget 時都可以正常載入。問題是我的系統(OS X 和 Linux)上的 DOMDocument::load() 沒有傳送任何 User-Agent 標頭,這導致 Microsoft-IIS/6.0 因某些奇怪的原因而回應 500 錯誤。

解決方案可以在 https://php.dev.org.tw/manual/en/function.libxml-set-streams-context.php 上找到。

<?php
$opts
= array(
'http' => array(
'user_agent' => 'PHP libxml agent',
)
);

$context = stream_context_create($opts);
libxml_set_streams_context($context);

// 透過 HTTP 請求檔案
$doc = DOMDocument::load('http://www.example.com/file.xml');
?>
2
hh dot lohmann at yahoo dot de
17 年前
BadGuy 的註解可能會造成混淆,因為他描述的並非相關方法的特殊屬性。PHP 總是會在本地檔案系統中工作,這表示如果您想使用來自其他系統的資源,或者 - 實際上是 BadGuy 的問題 - 需要其他程式或處理程序處理過的資源,您必須在程式碼中明確地聲明和管理。在這方面,PHP 就像一個很正常的程式。

BadGuy 的解決方案是使用「http 包裝器」來取得另一個處理程序的輸出(請參閱 PHP 手冊中的「包裝器」)。執行此操作時,必須遵守 http 呼叫的適當語法。
2
admin at tijnema dot tijnema dot info
17 年前
回覆 BadGuy [at] BadGuy [dot] nl

當 news.php 檔案位於同一台伺服器上時,就像您在第一個範例中所說的那樣,http://my.beautiful-website.com/xmlsource/news.php 無法運作,但您應該使用 https://127.0.0.1/xmlsource/news.phphttp://127.0.0.1/xmlsource/news.php
3
the_N_Channel
16 年前
請注意,如果檔案開頭在 <?xml version="1.0" ?> 宣告之前有註解,則將無法成功載入!
3
BadGuy [at] BadGuy [dot] nl
17 年前
請注意,此方法會先使用本地檔案系統,然後才執行任何遠端操作。 「缺點」是,如果您執行以下操作
<?php
$xml
= new DOMDocument;
$xml->load("xmlsource/news.php");
?>

這不會讓該方法讀取 news.php 檔案的實際輸出(大概是有效的 xml 資料),而是讀取檔案內容(很明顯,這會是 php 程式碼)。因此,這會回傳一個錯誤,指出 news.php 缺少 xml 宣告,或許也缺少 xml 開始標籤

以下方法會有效

<?php
$xml
= new DOMDocument;
$xml->load("http://my.beautiful-website.com/xmlsource/news.php");
?>

這會強制使用 http 請求來取得此檔案,而不是僅在本機讀取它,而檔案僅回傳程式碼
1
sainthyoga2003 at gmail dot com
12 年前
在預設範例中

<?php
$doc
= new DOMDocument();
$doc->load('book.xml');
echo
$doc->saveXML();
?>

您必須輸入 book.xml 的絕對路徑,才能在 load 函式中取得 false 的結果。
1
Raf-sns
1 年前
請注意選項「preserveWhiteSpace」

$dom = new DOMDocument;
// false -> 這會保留空白
// true -> 這會將所有項目放在同一行
$dom->preserveWhiteSpace = false; // 保留空白!
0
sainthyoga2003 at gmail dot com
13 年前
我找到了 xml:id 警告的部分解決方案,此解決方案已在此網址說明:https://fosswiki.liip.ch/display/BLOG/GetElementById+Pitfalls

該處說明
ID 必須是有效的 NCName,例如,這表示第一個字母不能是數字。

而我的 xml:id 中剛好有個數字。 :D
0
_ michael
14 年前
XHTML 和實體:下方由 zachatwork at gmail dot com 提出的解決方案對我無效。我檢查過多個伺服器(LAMPP 和 WAMPP 都有) - 在每個伺服器上,使用 LIBXML_DTDLOAD 選項呼叫 loadXML() 都會觸發外部 DTD 請求。這可不是好消息。

如果 allow_url_fopen 關閉,則對 DTD 的請求會因警告而失敗。如果它開啟,請求會失敗,因為這些 w3c URL 會傳回 503 服務無法使用。

在任何情況下,HTML 實體仍然會產生警告。

就我所知,最好的解決方案就是忽略警告並使用 '@' 來抑制它們。我不建議使用 loadHTML() 而不是 loadXML() 來解析 XHTML - 是的,你擺脫了實體問題,但 loadHTML() 在解析時會更改來源(嘗試「修復」它,即使沒有任何需要修復的)。
0
syntaxiko
15 年前
如果使用 XML DOM PECL 模組,此函式將無法運作
-2
daevid at daevid dot com
19 年前
假設您想從 .XSD 檔案動態載入陣列。這個方法就是您的好幫手。只要記得在 xpath 等中使用實際的 xs: 部分。

所有其他「載入」方法都會出錯。

<?php
$attributes
= array();
$xsdstring = "/htdocs/api/xsd/common.xsd";
$XSDDOC = new DOMDocument();
$XSDDOC->preserveWhiteSpace = false;
if (
$XSDDOC->load($xsdstring))
{
$xsdpath = new DOMXPath($XSDDOC);
$attributeNodes =
$xsdpath->
query('//xs:simpleType[@name="attributeType"]')
->
item(0);
foreach (
$attributeNodes->childNodes as $attr)
{
$attributes[ $attr->getAttribute('value') ] = $attr->getAttribute('name');
}
unset(
$xsdpath);
}
print_r($attributes);
?>
-2
_ michael
14 年前
load() 會根據 XML 宣告的詳細資訊處理非 ASCII 字元,但方式有點令人意外。人們會假設宣告 '<?xml version="1.0" encoding="UTF-8"?>' 和 '<?xml version="1.0"?>' 的處理方式相同,因為 UTF-8 畢竟是預設編碼。但事實並非如此。

* 如果有 XML 宣告 *明確地* 定義了編碼,則非 ASCII 字元會保持不變。
* 如果 XML 宣告沒有明確定義編碼,或者如果 XML 宣告遺失,則非 ASCII 字元會轉換為數值實體。

因此,文件

<?xml version="1.0"?>
<root><nonascii>ä</nonascii></root>

將會轉換為

<?xml version="1.0"?>
<root><nonascii>&#xE4;</nonascii></root>

如果完全沒有 XML 宣告,也會發生相同的情況。另一方面,文件

<?xml version="1.0" encoding="UTF-8"?>
<root><nonascii>ä</nonascii></root>

將保持原樣。

此行為也適用於 loadXML()。
-2
darren at viamedia dot co dot za
16 年前
如果您載入 XML 的目的是要針對內部 DTD 進行驗證,並且您遇到驗證問題,則可能與缺少 LIBXML 常數有關。

我發現「aidan at php dot net」在根層級 dom 文件中的這篇文章,認為它在這裡可能更有用
從 PHP 5.1 開始,libxml 選項可以使用常數來設定,而不是使用專有的 DomDocument 屬性。

DomDocument->resolveExternals 等同於設定
LIBXML_DTDLOAD
LIBXML_DTDATTR

DomDocument->validateOnParse 等同於設定
LIBXML_DTDLOAD
LIBXML_DTDVALID

建議 PHP 5.1 使用者使用新的常數。

範例
<?php
$dom
= new DOMDocument;
// 解析外部實體
$dom->load($file, LIBXML_DTDLOAD|LIBXML_DTDATTR);
// 或
// 針對 DTD 進行驗證
$dom->load($file, LIBXML_DTDLOAD|LIBXML_DTDVALID);
$dom->validate();
?>
-2
zachatwork at gmail dot com
15 年前
您可以輕鬆地使用 LIBXML_DTDLOAD 選項來避免關於 &nbsp; 參考的警告。

<?php

$html
= <<<EOF
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<p>&nbsp;</p>
</body>
</html>
EOF;

// 這個完美運作。
$dom = new DOMDocument();
$dom->loadXML($html, LIBXML_DTDLOAD);
print
$dom->saveXML();

// 這個會產生警告。
$dom = new DOMDocument();
$dom->loadXML($html);
print
$dom->saveXML();

?>

另請參閱:https://php.dev.org.tw/manual/en/libxml.constants.php

請注意,libxml 會偵測到您的 DTD 可透過 /etc/xml/catalog 在本地取得。因此,不必擔心這會導致您的 DOM 載入發出外部網路請求。
To Top