PHP 日本研討會 2024

DOMDocument 類別

(PHP 5, PHP 7, PHP 8)

簡介

代表整個 HTML 或 XML 文件;作為文件樹的根。

類別概要

class DOMDocument extends DOMNode implements DOMParentNode {
/* 繼承的常數 */
/* 屬性 */
public readonly ?DOMDocumentType $doctype;
public readonly ?DOMElement $documentElement;
public readonly ?string $actualEncoding;
public ?string $encoding;
public readonly ?string $xmlEncoding;
public ?string $version;
public readonly mixed $config;
public bool $recover;
public readonly ?DOMElement $firstElementChild;
public readonly ?DOMElement $lastElementChild;
public readonly int $childElementCount;
/* 繼承的屬性 */
public readonly string $nodeName;
public readonly int $nodeType;
public readonly ?DOMNode $parentNode;
public readonly ?DOMElement $parentElement;
public readonly DOMNodeList $childNodes;
public readonly ?DOMNode $firstChild;
public readonly ?DOMNode $lastChild;
public readonly ?DOMNode $previousSibling;
public readonly ?DOMNode $nextSibling;
public readonly ?DOMNamedNodeMap $attributes;
public readonly bool $isConnected;
public readonly ?DOMDocument $ownerDocument;
public readonly ?string $namespaceURI;
public string $prefix;
public readonly ?string $localName;
public readonly ?string $baseURI;
/* 方法 */
public __construct(string $version = "1.0", string $encoding = "")
public append(DOMNode|string ...$nodes): void
public createAttribute(string $localName): DOMAttr|false
public createAttributeNS(?string $namespace, string $qualifiedName): DOMAttr|false
public createElement(string $localName, string $value = ""): DOMElement|false
public createElementNS(?string $namespace, string $qualifiedName, string $value = ""): DOMElement|false
public getElementById(string $elementId): ?DOMElement
public getElementsByTagName(string $qualifiedName): DOMNodeList
public getElementsByTagNameNS(?string $namespace, string $localName): DOMNodeList
public importNode(DOMNode $node, bool $deep = false): DOMNode|false
public load(string $filename, int $options = 0): bool
public loadHTML(string $source, int $options = 0): bool
public loadHTMLFile(string $filename, int $options = 0): bool
public loadXML(string $source, int $options = 0): bool
public prepend(DOMNode|string ...$nodes): void
public registerNodeClass(string $baseClass, ?string $extendedClass): true
public relaxNGValidate (string $filename): bool
public replaceChildren (DOMNode|string ...$nodes): void
public save (string $filename, int $options = 0): int|false
public saveHTML (?DOMNode $node = null): string|false
public saveHTMLFile (string $filename): int|false
public saveXML (?DOMNode $node = null, int $options = 0): string|false
public schemaValidate (string $filename, int $flags = 0): bool
public schemaValidateSource (string $source, int $flags = 0): bool
public validate (): bool
public xinclude (int $options = 0): int|false
/* 繼承的方法 */
public DOMNode::C14N (
    bool $exclusive = false,
    bool $withComments = false,
    ?array $xpath = null,
    ?array $nsPrefixes = null
): string|false
public DOMNode::C14NFile (
    string $uri,
    bool $exclusive = false,
    bool $withComments = false,
    ?array $xpath = null,
    ?array $nsPrefixes = null
): int|false
public DOMNode::cloneNode (bool $deep = false): DOMNode|false
public DOMNode::getRootNode (?array $options = null): DOMNode
public DOMNode::insertBefore (DOMNode $node, ?DOMNode $child = null): DOMNode|false
public DOMNode::isEqualNode (?DOMNode $otherNode): bool
public DOMNode::isSameNode (DOMNode $otherNode): bool
public DOMNode::isSupported (string $feature, string $version): bool
}

屬性

actualEncoding

已於 PHP 8.4.0 棄用。文件的實際編碼,是與 encoding 對應的唯讀屬性。

childElementCount

子元素的數量。

config

已於 PHP 8.4.0 棄用。當呼叫 DOMDocument::normalizeDocument() 時使用的組態。

doctype

與此文件相關聯的文件類型宣告。

documentElement

作為第一個文件元素的 DOMElement 物件。如果找不到,此值會評估為 null

documentURI

文件的位置,如果未定義則為 null

encoding

文件的編碼,如 XML 宣告所指定。此屬性不存在於最終的 DOM Level 3 規格中,但在這個實作中是操作 XML 文件編碼的唯一方法。

firstElementChild

第一個子元素,若無則為 null

formatOutput

使用縮排和額外空格來美化輸出格式。如果文件在載入時啟用了 preserveWhitespace,則此設定無效。

implementation

處理此文件的 DOMImplementation 物件。

lastElementChild

最後一個子元素,若無則為 null

preserveWhiteSpace

不要移除多餘的空白。預設為 true。將此值設定為 false 的效果與將 LIBXML_NOBLANKS 作為 option 傳遞給 DOMDocument::load() 等方法相同。

recover

專有屬性。啟用復原模式,即嘗試剖析格式不正確的文件。此屬性不是 DOM 規格的一部分,而是 libxml 特有的。

resolveExternals

設定為 true 從文件類型宣告中載入外部實體。這對於在 XML 文件中包含字元實體很有用。

standalone

已棄用。文件是否為獨立的,如 XML 宣告所指定,對應於 xmlStandalone

strictErrorChecking

在發生錯誤時拋出 DOMException。預設為 true

substituteEntities

專有屬性。是否替換實體。此屬性不是 DOM 規格的一部分,而是 libxml 特有的。預設為 false

注意

啟用實體替換可能會導致 XML 外部實體 (XXE) 攻擊。

validateOnParse

載入並根據 DTD 驗證。預設為 false

注意

啟用 DTD 驗證可能會導致 XML 外部實體 (XXE) 攻擊。

version

已棄用。XML 的版本,對應於 xmlVersion

xmlEncoding

一個屬性,指定作為 XML 宣告的一部分,此文件的編碼。當未指定或未知時,例如在記憶體中建立 Document 時,此值為 null

xmlStandalone

一個屬性,指定作為 XML 宣告的一部分,此文件是否為獨立的。當未指定時,此值為 false。獨立文件是指沒有外部標記宣告的文件。此類標記宣告的一個例子是當 DTD 宣告具有預設值的屬性時。

xmlVersion

一個屬性,指定作為 XML 宣告的一部分,此文件的版本號。如果沒有宣告,且此文件支援 "XML" 功能,則值為 "1.0"。

變更記錄

版本 描述
8.4.0 actualEncodingconfig 現在已正式棄用。
8.0.0 DOMDocument 現在實作了 DOMParentNode
8.0.0 已移除未實作的方法 DOMDocument::renameNode()

注意事項

注意:

DOM 擴充功能使用 UTF-8 編碼。請使用 mb_convert_encoding()UConverter::transcode()iconv() 來處理其他編碼。

注意:

當在 DOMDocument 物件上使用 json_encode() 時,結果將會是對空物件進行編碼。

另請參閱

目錄

新增註解

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

Fernando H
16 年前
顯示如何使用此類別的快速範例,以便新使用者可以快速入門,而無需自己弄清楚所有內容。(在發布當天,此文件才剛添加,缺少範例。)

<?php

// 將內容類型設定為 XML,以便瀏覽器將其識別為 XML。
header( "content-type: application/xml; charset=ISO-8859-15" );

//「建立」文件。
$xml = new DOMDocument( "1.0", "ISO-8859-15" );

// 建立一些元素。
$xml_album = $xml->createElement( "Album" );
$xml_track = $xml->createElement( "Track", "第九號交響曲" );

// 設定屬性。
$xml_track->setAttribute( "length", "0:01:15" );
$xml_track->setAttribute( "bitrate", "64kb/s" );
$xml_track->setAttribute( "channels", "2" );

// 建立另一個元素,只是為了展示您可以新增任意(對電腦來說實際的)數量的子層級。
$xml_note = $xml->createElement( "Note", "路德維希·范·貝多芬創作的最後一首交響曲。" );

// 附加整個群組。
$xml_track->appendChild( $xml_note );
$xml_album->appendChild( $xml_track );

// 使用一些不同的值重複上述操作..
$xml_track = $xml->createElement( "Track", "公路藍調" );

$xml_track->setAttribute( "length", "0:01:33" );
$xml_track->setAttribute( "bitrate", "64kb/s" );
$xml_track->setAttribute( "channels", "2" );
$xml_album->appendChild( $xml_track );

$xml->appendChild( $xml_album );

// 解析 XML。
print $xml->saveXML();

?>

輸出
<Album>
<Track length="0:01:15" bitrate="64kb/s" channels="2">
第九號交響曲
<Note>
路德維希·范·貝多芬創作的最後一首交響曲。
</Note>
</Track>
<Track length="0:01:33" bitrate="64kb/s" channels="2">公路藍調</Track>
</Album>

如果您希望您的 PHP->DOM 程式碼在 .xml 副檔名下執行,您應該設定您的網頁伺服器以使用 PHP 執行 .xml 副檔名(請參閱 PHP 的安裝/設定說明,了解如何執行此操作)。

請注意,這
<?php
$xml
= new DOMDocument( "1.0", "ISO-8859-15" );
$xml_album = $xml->createElement( "Album" );
$xml_track = $xml->createElement( "Track" );
$xml_album->appendChild( $xml_track );
$xml->appendChild( $xml_album );
?>

與此不同
<?php
// 將無法運作。
$xml = new DOMDocument( "1.0", "ISO-8859-15" );
$xml_album = new DOMElement( "Album" );
$xml_track = new DOMElement( "Track" );
$xml_album->appendChild( $xml_track );
$xml->appendChild( $xml_album );
?>

雖然這會有效
<?php
$xml
= new DOMDocument( "1.0", "ISO-8859-15" );
$xml_album = new DOMElement( "Album" );
$xml->appendChild( $xml_album );
?>
developer at nabtron dot com
8 年前
對於那些來到這裡並檢查 utf-8 字元編碼問題的人,可以很容易地更正它,而無需在您的 html 中新增任何其他輸出標籤。

我們將使用:mb_convert_encoding

感謝之前評論中分享 SmartDOMDocument 的使用者,我得到了解決此問題的想法。但是,我真的希望他分享方法,而不是提供連結。

無論如何,回到解決方案,您可以簡單地使用

<?php

// 檢查我們收到的內容是否為空,以避免警告
if ( empty( $content ) ) {
return
false;
}

// 將所有特殊字元轉換為 utf-8
$content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8');

// 建立新文件
$doc = new DOMDocument('1.0', 'utf-8');

// 關閉一些錯誤
libxml_use_internal_errors(true);

// 它會載入內容,而不會新增封閉的 html/body 標籤和 doctype 宣告
$doc->LoadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

// 現在對此程式碼執行您想執行的任何操作

?>

我希望它能解決某些人的問題!如果您需要我的協助或服務來修正您的程式碼,您可以在 nabtron.com 上找到我,或透過此評論中提及的電子郵件與我聯絡。
jay at jaygilford dot com
14 年前
這是我編寫的一個小函數,用於使用 DOMDocument 取得所有頁面連結,希望對其他人有用

<?php
/**
* @author Jay Gilford
*/

/**
* get_links()
*
* @param string $url
* @return array
*/
function get_links($url) {

// 建立一個新的 DOM 文件來存放網頁結構
$xml = new DOMDocument();

// 將網址的內容載入到 DOM 中
$xml->loadHTMLFile($url);

// 空陣列,用來存放所有要回傳的連結
$links = array();

// 迴圈遍歷 DOM 中每個 <a> 標籤,並將其加入連結陣列
foreach($xml->getElementsByTagName('a') as $link) {
$links[] = array('url' => $link->getAttribute('href'), 'text' => $link->nodeValue);
}

// 回傳連結
return $links;
}
?>
andreas at userbrain dot com
3 年前
在掙扎了數小時解析和修改部分 HTML 內容後,我找到了這個對我有效的解決方案,與我在網路上找到的其他解決方案相比,這個方案相對簡單。

這個解決方案修正了不想要的 DOCTYPE 和 html、body 標籤,以及編碼問題。

<?php

// 假設:內容是 utf-8 編碼
$content = "<h1>This is a heading</h1><p>This is a paragraph</p>";

// 將內容載入到 div 並使用 meta 標籤指定編碼
$temp_dom = new DOMDocument();
$temp_dom->loadHTML("<meta http-equiv='Content-Type' content='charset=utf-8' /><div>$content</div>");

// 因為 loadHTML() 會加入 DOCTYPE 以及 <html> 和 <body> 標籤,所以我們建立另一個 DOMDocument 並只導入我們想要的節點
$dom = new DOMDocument();
$first_div = $temp_dom->getElementsByTagName('div')[0];
$first_div_node = $dom->importNode($first_div, true);
$dom->appendChild($first_div_node);

// 執行您想執行的任何操作
$dom->getElementsByTagName('h1')[0]->setAttribute('class', 'happy');

// 如果您不介意 div 和空白,也可以直接 echo $dom->saveHtml()
echo substr(trim($dom->saveHtml()), 5, -6);

// 輸出: <h1 class="happy">This is a heading</h1><p>This is a paragraph</p>
?>
tloach at gmail dot com
14 年前
對於其他在 formatOuput 無法正常運作方面遇到問題的人,這裡有一個解決方案

不要只是做像這樣的操作

<?php
$outXML
= $xml->saveXML();
?>

強制它從頭重新載入 XML,這樣它就會正確格式化

<?php
$outXML
= $xml->saveXML();
$xml = new DOMDocument();
$xml->preserveWhiteSpace = false;
$xml->formatOutput = true;
$xml->loadXML($outXML);
$outXML = $xml->saveXML();
?>
biker dot mike at gmx dot com
8 年前
從字串載入 XML 時,請注意以下陷阱

<?php
$doc
= new \DOMDocument;
$doc->documentURI = $myXmlFilename;
$doc->loadXML($myXmlString);
?>

現在 documentURI 已設定為 $myXmlFilename 的值,對吧?

錯了!

它被設定為目前的工作目錄。如果您想手動將 documentURI 設定為 CWD 以外的其他值,請在呼叫 loadXML() 後執行此操作。

例如:
<?php
$doc
= new \DOMDocument;
$doc->loadXML($myXmlString);
$doc->documentURI = $myXmlFilename;
?>

documentURI 現在確實設定為 $myXmlFilename 的值。
Nick M
13 年前
您可能需要將 DOMDocument 的全部或部分儲存為 XHTML 相容的字串,使其符合 XML 和 HTML 4。以下是擴充了 saveXHTML 方法的 DOMDocument 類別

<?php

/**
* XHTML 文件
*
* 代表整個 XHTML DOM 文件;作為文件樹的根目錄。
*/
class XHTMLDocument extends DOMDocument {

/**
* 這些標籤必須永遠自行終止。其他任何標籤都絕不能自行終止。
*
* @var array
*/
public $selfTerminate = array(
'area','base','basefont','br','col','frame','hr','img','input','link','meta','param'
);

/**
* saveXHTML
*
* 將內部 XML 樹轉儲回 XHTML 相容的字串。
*
* @param DOMNode $node
* 使用此參數來僅輸出特定節點,而非整個文件。
*/
public function saveXHTML(DOMNode $node=null) {

if (!
$node) $node = $this->firstChild;

$doc = new DOMDocument('1.0');
$clone = $doc->importNode($node->cloneNode(false), true);
$term = in_array(strtolower($clone->nodeName), $this->selfTerminate);
$inner='';

if (!
$term) {
$clone->appendChild(new DOMText(''));
if (
$node->childNodes) foreach ($node->childNodes as $child) {
$inner .= $this->saveXHTML($child);
}
}

$doc->appendChild($clone);
$out = $doc->saveXML($clone);

return
$term ? substr($out, 0, -2) . ' />' : str_replace('><', ">$inner<", $out);

}

}

?>

這個方法尚未經過效能測試,但可能比 saveXML 或 saveHTML 慢得多,應謹慎使用。
pastormontesinos at gmail dot com
3 年前
為了在解析時安全地使用腳本節點,最好的選擇是擴展 DOMDocument,在 DOMDocument 處理時保留 script 標籤,並在調用 saveHTML 函數後重新排列它們。這是我的自定義類別。

<?php

class SafeDOMDocument extends \DOMDocument
{
const
REGEX_JS = '#(\s*<!--(\[if[^\n]*>)?\s*(<script.*</script>)+\s*(<!\[endif\])?-->)|(\s*<script.*</script>)#isU';
const
SUBSTITUTION_FORMAT = '<!--<script class="script_%s"></script>-->';
private
$matchedScripts = [];

public function
loadHTML($source, $options = 0)
{
$this->formatOutput = false;
$this->preserveWhiteSpace = true;
$this->validateOnParse = false;
$this->strictErrorChecking = false;
$this->recover = false;
$this->resolveExternals = false;
$this->substituteEntities = false;
$matches = [];
$success = preg_match_all(self::REGEX_JS, $source, $matches);

if (
$success && !empty($matches)) {
foreach (
$matches[0] as $match) {
$storedScript = rtrim(ltrim($match, "\n\r\t "), "\n\r\t ");
$scriptId = md5($storedScript);
$key = sprintf(self::SUBSTITUTION_FORMAT, $scriptId);
$source = str_replace($match, $key, $source);
$this->matchedScripts[$key] = $storedScript;
}
}

return
parent::loadHTML($source, $options);
}

public function
saveHTML(DOMNode $node = null)
{
$output = parent::saveHTML($node);

if (
count($this->matchedScripts)) {
foreach (
$this->matchedScripts as $substitution => $originalSnippet) {
$output = str_replace($substitution, $originalSnippet, $output);
}
}

return
$output;
}
}
?>
evert at er dot nl
14 年前
我寫了一個簡單又好用的節點轉陣列的函式,值得一試 ;)

<?php
function getArray($node)
{
$array = false;

if (
$node->hasAttributes())
{
foreach (
$node->attributes as $attr)
{
$array[$attr->nodeName] = $attr->nodeValue;
}
}

if (
$node->hasChildNodes())
{
if (
$node->childNodes->length == 1)
{
$array[$node->firstChild->nodeName] = $node->firstChild->nodeValue;
}
else
{
foreach (
$node->childNodes as $childNode)
{
if (
$childNode->nodeType != XML_TEXT_NODE)
{
$array[$childNode->nodeName][] = $this->getArray($childNode);
}
}
}
}

return
$array;
}
?>
fcartegnie
15 年前
請小心 formatOutput() 的使用。

像這樣建立一個空的節點
createElement('foo','')
而不是
createElement('foo')
會導致 formatOutput 失效。
devour at php dot net
2 個月前
雖然 DOMDocument 在技術上可以用於解析 HTML,但它並非 HTML 文件理想的選擇,更適合處理格式良好的 XML。使用 DOMDocument 處理 HTML 的主要問題之一是它對特殊字元(例如 & 符號 (&))的嚴格處理。

DOMDocument 要求 & 符號必須轉義為 &amp;,這符合 XML 標準,但對於處理真實世界的 HTML 來說可能違反直覺,在真實世界的 HTML 中,常見未經轉義的 & 字符,尤其是在 URL 和文字中。這種行為源自底層的基於 XML 的解析器 (libxml),它像處理 XML 一樣嚴格處理 HTML。

早在 2001 年就有人回報過這個問題,但今天在 HTML 文件上使用 DOMDocument 時,仍然會出現相同的解析錯誤。

開發人員常用的變通方法是抑制 DOMDocument 的錯誤報告,尤其是在出現未轉義的 & 符號等解析錯誤時。但是,不建議抑制這些錯誤,尤其是在生產環境中,因為它可能會隱藏重要的問題並構成潛在的安全風險。忽略或抑制錯誤可能會導致警告沒有被注意到,如果沒有正確處理,可能會導致漏洞。

基於這些原因,建議主要將 DOMDocument 用於 XML 文件,或者在處理 HTML 時考慮更合適的函式庫,以避免這些問題。

theCoder / MV
cmyk777 at gmail dot com
15 年前
此函式可能有助於偵錯目前的 DOM 元素

<?php
function dom_dump($obj) {
if (
$classname = get_class($obj)) {
$retval = "Instance of $classname, node list: \n";
switch (
true) {
case (
$obj instanceof DOMDocument):
$retval .= "XPath: {$obj->getNodePath()}\n".$obj->saveXML($obj);
break;
case (
$obj instanceof DOMElement):
$retval .= "XPath: {$obj->getNodePath()}\n".$obj->ownerDocument->saveXML($obj);
break;
case (
$obj instanceof DOMAttr):
$retval .= "XPath: {$obj->getNodePath()}\n".$obj->ownerDocument->saveXML($obj);
//$retval .= $obj->ownerDocument->saveXML($obj);
break;
case (
$obj instanceof DOMNodeList):
for (
$i = 0; $i < $obj->length; $i++) {
$retval .= "Item #$i, XPath: {$obj->item($i)->getNodePath()}\n".
"{$obj->item($i)->ownerDocument->saveXML($obj->item($i))}\n";
}
break;
default:
return
"Instance of unknown class";
}
} else {
return
'no elements...';
}
return
htmlspecialchars($retval);
}
?>

範例用法

<?php
$dom
= new DomDocument();
$dom->load('test.xml');
$body = $dom->documentElement->getElementsByTagName('book');
echo
'<pre>'.dom_dump($body).'<pre>';
?>

輸出

DOMNodeList 的實例,節點列表
項目 #0,XPath: /library/book[1]
<book isbn="0345342968">
<title>華氏 451 度</title>
<author>雷·布萊伯利</author>
<publisher>德爾雷</publisher>
</book>
項目 #1,XPath: /library/book[2]
<book isbn="0048231398">
<title>精靈寶鑽</title>
<author>J.R.R. 托爾金</author>
<publisher>喬治·艾倫與安溫</publisher>
</book>
項目 #2,XPath: /library/book[3]
<book isbn="0451524934">
<title>一九八四</title>
<author>喬治·歐威爾</author>
<publisher>新號出版社</publisher>
</book>
項目 #3,XPath: /library/book[4]
<book isbn="031219126X">
<title>科學怪人</title>
<author>瑪麗·雪萊</author>
<publisher>貝德福德</publisher>
</book>
項目 #4,XPath: /library/book[5]
<book isbn="0312863551">
<title>月亮是嚴厲的老師</title>
<author>羅伯特·海萊因</author>
<publisher>軌域出版社</publisher>
</book>
sites.sitesbr.net
11 年前
如何將具有如下層級的 DomDocument 物件化
<root>
<item>
<prop1>info1</prop1>
<prop2>info2</prop2>
<prop3>info3</prop3>
</item>
<item>
<prop1>info1</prop1>
<prop2>info2</prop2>
<prop3>info3</prop3>
</item>
</root>

是否可以像物件一樣存取資訊,例如

<?php
$theNodeValue
= $aitem->prop1;
?>

以下是程式碼:一個類別和 2 個函式。

<?php
class ArrayNode{
public
$nodeName, $nodeValue;
}

function
getChildNodeElements( $domNode ){
$nodes = array();
for(
$i=0; $i < $domNode->childNodes->length; $i++){
$cn = $domNode->childNodes->item($i);
if(
$cn->nodeType == 1){
$nodes[] = $cn;
}
}
return
$nodes;
}

function
getArrayNodes( $domDoc ){
$res = array();

for(
$i=0; $i < $domDoc->childNodes->length; $i++){
$cn = $domDoc->childNodes->item($i);
# 第一個是根標籤...
if( $cn->nodeType == 1){
# 但我們要的是它的 childNodes。
$sub_cn = getChildNodeElements( $cn);
# 找到標籤名稱:
$baseItemTagName = $sub_cn[0]->nodeName;
break;
}
}

$dnl = $domDoc->getElementsByTagName( $baseItemTagName);

for(
$i=0; $i< $dnl->length; $i++){
$arrayNode = new ArrayNode();

# 摘要
$arrayNode->nodeName = $dnl->item($i)->nodeName;
$arrayNode->nodeValue = $dnl->item($i)->nodeValue;

# 子節點
$cn = $dnl->item($i)->childNodes;
for(
$k=0; $k<$cn->length; $k++){
if(
$cn->item($k)->nodeName == "#text" && trim($cn->item($k)->nodeValue) == "") continue;
$arrayNode->{$cn->item($k)->nodeName} = $cn->item($k)->nodeValue;
}

# 屬性
$attr = $dnl->item($i)->attributes;
for(
$k=0; $k < $attr->length; $k++){
if(!
is_null($attr)){
if(
$attr->item($k)->nodeName == "#text" && trim($attr->item($k)->nodeValue) == "") continue;
$arrayNode->{$attr->item($k)->nodeName} = $attr->item($k)->nodeValue;
}
}

$res[] = $arrayNode;

}

return
$res;
}
?>

使用方法

<?php

# 首先,您需要將 XML 載入到一個 DomDocument 變數中。

$url = "/path/to/yourxmlfile.xml";
$domSrc = file_get_contents($url);
$dom = new DomDocument();
$dom->loadXML( $domSrc );

# 接著,從 DomDocument 取得 ArrayNodes。

$ans = getArrayNodes( $dom );


for(
$i=0; $i < count( $ans ) ; $i++){

$cn = $ans[ $i];

$info1 = $cn->prop1;
$info2 = $cn->prop2;
$info3 = $cn->prop3;

// ...

}

?>
610010559 at qq dot com
2 年前
當您透過 appendChild() 方法將新元素新增到格式化的 XML 資料時,您會發現您新增的新元素沒有被格式化(也就是沒有索引,沒有換行)。這是我的解決方案(簡而言之,載入 XML 時不保留空白),範例如下所示:
<?php
$doc
= new \DOMDocument();
$doc->formatOutput = true;
$doc->preserveWhiteSpace = false;//這是關鍵,預設值是 true。
$doc->loadXML($xmlStr);
$doc->appendChild($doc->createElement('php', '666'));
$formattedXMLStr = $doc->saveXML();//DOMDocument 會為您格式化 XML 字串
echo $formattedXMlStr;
?>
我花了一些時間才嘗試出來。希望這可以節省您的時間。
ashjkshdu283 at gmail dot com
6 年前
/* 此函數由 jay at jaygilford dot com 的貼文演變而來
* 此函數將返回指定
* 屬性 ($attr) 的值陣列,適用於所有 DomDocument 物件的元素
*/

<?php

function getAttrData(string $attr, DomDocument $dom) {
// 用於存放所有要返回的類別的空陣列
$attrData = array();

// 迴圈遍歷 dom 中的每個標籤,並將其屬性資料新增到陣列中
foreach($dom->getElementsByTagName('*') as $tag) {
if(empty(
$tag->getAttribute($attr)) === false) {
array_push($attrData, $tag->getAttribute($attr));
}
}

// 返回屬性資料的陣列
return array_unique($attrData);
}

$html = '
<!DOCTYPE html>
<html>
<head>
<title>頁面標題</title>
</head>
<body>
<a href="#someLink" id="someLink" class="link-class">一些連結</a>
<a href="#someOtherLink" id="someOtherLink" class="link-class">其他連結</a>
<h1 id="header1" class="header-class">我的第一個標題</h1>
<p id="para1" class="para-class">我的第一個段落。</p>
</body>
</html>'
;
$dom = new DOMDocument();
$dom->loadHtml($html);
$dom->saveHTML();
var_dump(getAttrData('class', $dom));
ingjetel at gmail dot com
9 年前
透過 DOM 解析簡單輸出 XML 檔案的簡易函式

<?php
$dom
= new DomDocument();
$dom->load("./file.xml") or die("錯誤");
$start = $dom->documentElement;
fc($start);

function
fc($node) {
$child = $node->childNodes;
foreach(
$child as $item) {
if (
$item->nodeType == XML_TEXT_NODE) {
if (
strlen(trim($item->nodeValue))) echo trim($item->nodeValue)."<br/>";
}
else if (
$item->nodeType == XML_ELEMENT_NODE) fc($item);
}
}
?>
danny dot nunez15 at gmail dot com
11 年前
一個簡單的函式,用於抓取頁面中的所有連結。

function get_links($url) {

// 建立一個新的 DOM 文件來保存我們的網頁結構
$xml = new DOMDocument();

// 將網址的內容載入 DOM 中

$xml->loadHTMLFile($url);

// 用於存放所有要返回的連結的空陣列
$links = array();

// 迴圈遍歷 dom 中的每個 <a> 標籤,並將其新增到連結陣列中
foreach ($xml->getElementsByTagName('a') as $link) {
$url = $link->getAttribute('href');
if (!empty($url)) {
$links[] = $link->getAttribute('href');
}
}

// 返回連結
return $links;
}
admin at beerpla dot net
14 年前
在看到許多關於某些 DOMDocument 缺點的抱怨,例如錯誤的編碼處理以及始終以 <html>、<head> 和 DOCTYPE 保存 HTML 片段後,我決定需要一個更好的解決方案。

所以這就是:SmartDOMDocument。您可以在 http://beerpla.net/projects/smartdomdocument/ 找到它

目前,主要的亮點是

- SmartDOMDocument 繼承自 DOMDocument,因此非常易於使用 - 只需宣告一個 SmartDOMDocument 類型的物件,而不是 DOMDocument,即可在所有現有功能之上享受新的行為(請參閱以下範例)。

- saveHTMLExact() - DOMDocument 有一個設計非常糟糕的「功能」,如果載入的 HTML 程式碼不包含 <html> 和 <body> 標籤,它會自動新增它們(是的,沒有任何標誌可以關閉此行為)。
因此,當您呼叫 $doc->saveHTML() 時,您新保存的內容現在會包含 <html><body> 和 DOCTYPE。當嘗試處理程式碼片段時不是很方便(XML 有類似的問題)。
SmartDOMDocument 包含一個名為 saveHTMLExact() 的新函式,它可以準確地執行您想要的操作 - 它會保存 HTML,而不會新增 DOMDocument 會新增的額外垃圾。

- 編碼修復 - DOMDocument 眾所周知無法正確處理編碼(至少是 UTF-8),並且會損壞輸出。
SmartDOMDocument 嘗試透過增強 loadHTML() 來正確處理編碼來解決此問題。此行為對您而言是透明的 - 只需像平常一樣使用 loadHTML() 即可。

- SmartDOMDocument 物件作為字串 - 您可以使用 SmartDOMDocument 物件作為字串,它會印出其內容。
例如
<?php
echo "這是 HTML:$smart_dom_doc";
?>

我將維護此程式碼並嘗試修復收到的錯誤。

請享用。
qrworld.net
10 年前
在這篇文章 http://softontherocks.blogspot.com/2014/11/descargar-el-contenido-de-una-url_11.html 中,我找到一個簡單的方法,可以使用 DOMDocument、loadHTMLFile 和 saveHTML() 來取得 URL 的內容。

function getURLContent($url){
$doc = new DOMDocument;
$doc->preserveWhiteSpace = FALSE;
@$doc->loadHTMLFile($url);
return $doc->saveHTML();
}
To Top