2024 PHP Conference Japan

DOMNode 類別

(PHP 5, PHP 7, PHP 8)

類別概要

類別 DOMNode {
/* 常數 */
公開 常數 整數 DOCUMENT_POSITION_PRECEDING = 0x2;
公開 常數 整數 DOCUMENT_POSITION_FOLLOWING = 0x4;
公開 常數 整數 DOCUMENT_POSITION_CONTAINS = 0x8;
/* 屬性 */
公開 唯讀 字串 $nodeName;
公開 唯讀 整數 $nodeType;
公開 唯讀 ?DOM 節點 $parentNode;
公開 唯讀 ?DOM 元素 $parentElement;
公開 唯讀 ?DOM 節點 $firstChild;
公開 唯讀 ?DOM 節點 $lastChild;
公開 唯讀 ?DOM 節點 $nextSibling;
公開 唯讀 布林值 $isConnected;
公開唯讀
公開唯讀 ?string $namespaceURI;
公開 string $prefix;
公開唯讀 ?string $localName;
公開唯讀 ?string $baseURI;
公開 string $textContent;
/* 方法 */
公開 appendChild(DOMNode $node): DOMNode|false
公開 C14N(
    bool $exclusive = false,
    bool $withComments = false,
    ?array $xpath = null,
    ?array $nsPrefixes = null
): string|false
公開 C14NFile(
    string $uri,
    bool $exclusive = false,
    bool $withComments = false,
    ?array $xpath = null,
    ?array $nsPrefixes = null
): int|false
公開 cloneNode(bool $deep = false): DOMNode|false
公開 節點相等(?DOM 節點 $otherNode): 布林值
公開 已支援(字串 $feature, 字串 $version): 布林值
公開 lookupPrefix(字串 $namespace): ?字串
公開 normalize():
公開 replaceChild(DOMNode $node, DOMNode $child): DOMNode|false
公開 __sleep(): 陣列
公開 __wakeup():
}

預定義常數

DOMNode::DOCUMENT_POSITION_DISCONNECTED
當其他節點和參考節點不在同一棵樹中時設定。
DOMNode::DOCUMENT_POSITION_PRECEDING
當其他節點在參考節點之前時設定。
DOMNode::DOCUMENT_POSITION_FOLLOWING
當其他節點在參考節點之後時設定。
DOMNode::DOCUMENT_POSITION_CONTAINS
當其他節點是參考節點的祖先節點時設定。
DOMNode::DOCUMENT_POSITION_CONTAINED_BY
當其他節點是參考節點的子孫節點時設定。
DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
當結果取決於特定實作行為且可能無法移植時設定。這可能發生在斷開連線的節點或屬性節點上。

屬性

nodeName

傳回目前節點類型的最精確名稱

nodeValue

此節點的值,取決於其類型。與 W3C 規範相反,DOMElement 節點的節點值等於 DOMNode::textContent 而不是 null

nodeType

取得節點的類型。預定義的 XML_*_NODE 常數之一

parentNode

此節點的父節點。如果沒有這樣的節點,則傳回 null

parentElement

此元素的父元素。如果沒有這樣的元素,則傳回 null

childNodes

包含此節點所有子節點的 DOMNodeList。如果沒有子節點,則為空的 DOMNodeList

firstChild

此節點的第一個子節點。如果沒有這樣的節點,則傳回 null

lastChild

此節點的最後一個子節點。如果沒有這樣的節點,則傳回 null

previousSibling

緊接在此節點之前的節點。如果沒有這樣的節點,則傳回 null

nextSibling

緊接在此節點之後的節點。如果沒有這樣的節點,則傳回 null

attributes

包含此節點屬性的 DOMNamedNodeMap(如果它是 DOMElement 的話),否則為 null

isConnected

節點是否連接到文件

ownerDocument

與此節點關聯的 DOMDocument 物件,如果此節點是 DOMDocument 則為 null

namespaceURI

此節點的命名空間 URI,如果未指定,則為 null

prefix

此節點的命名空間前綴。

localName

返回此節點的限定名稱的本地部分。

baseURI

此節點的絕對基礎 URI,如果實作無法取得絕對 URI,則為 null

textContent

此節點及其後代的文字內容。

更新日誌

版本 說明
8.4.0 新增了 DOMNode::compareDocumentPosition() 方法。
8.4.0 新增了常數 DOMNode::DOCUMENT_POSITION_DISCONNECTEDDOMNode::DOCUMENT_POSITION_PRECEDINGDOMNode::DOCUMENT_POSITION_FOLLOWINGDOMNode::DOCUMENT_POSITION_CONTAINSDOMNode::DOCUMENT_POSITION_CONTAINED_BYDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
8.3.0 新增了 DOMNode::contains()DOMNode::isEqualNode() 方法。
8.3.0 新增了屬性 DOMNode::$parentElementDOMNode::$isConnected
8.0.0 已移除未實作的方法 DOMNode::compareDocumentPosition()DOMNode::isEqualNode()DOMNode::getFeature()DOMNode::setUserData()DOMNode::getUserData()

注意事項

注意:

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

另請參閱

目錄

新增註記

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

42
marc at ermshaus dot org
15 年前
我花了好久才找到 XML_*_NODE 常數的對應表。所以我想,把它貼在這裡會很方便

1 XML_ELEMENT_NODE (元素節點)
2 XML_ATTRIBUTE_NODE (屬性節點)
3 XML_TEXT_NODE (文字節點)
4 XML_CDATA_SECTION_NODE (CDATA 區段節點)
5 XML_ENTITY_REFERENCE_NODE (實體參考節點)
6 XML_ENTITY_NODE (實體節點)
7 XML_PROCESSING_INSTRUCTION_NODE (處理指令節點)
8 XML_COMMENT_NODE (註釋節點)
9 XML_DOCUMENT_NODE (文件節點)
10 XML_DOCUMENT_TYPE_NODE (文件類型節點)
11 XML_DOCUMENT_FRAGMENT_NODE (文件片段節點)
12 XML_NOTATION_NODE (標記法節點)
22
David Rekowski
14 年前
您不能直接覆寫 $textContent 來取代 DOMNode 的文字內容,如同缺少唯讀旗標所暗示的。相反地,您必須執行以下操作

<?php

$node
->removeChild($node->firstChild);
$node->appendChild(new DOMText('新的文字內容'));

?>

此範例顯示了會發生什麼事

<?php

$doc
= DOMDocument::loadXML('<node>old content</node>');
$node = $doc->getElementsByTagName('node')->item(0);
echo
"內容 1: ".$node->textContent."\n";

$node->textContent = 'new content';
echo
"內容 2: ".$node->textContent."\n";

$newText = new DOMText('new content');

$node->appendChild($newText);
echo
"內容 3: ".$node->textContent."\n";

$node->removeChild($node->firstChild);
$node->appendChild($newText);
echo
"內容 4: ".$node->textContent."\n";

?>

輸出結果為

內容 1: old content // 初始內容
內容 2: new content // 嘗試透過覆寫 $node->textContent 來取代內容
內容 3: new contentnew content // 直接附加新的文字節點
內容 4: new content // 在附加新的文字節點之前先移除第一個子節點

如果您想要使用 CDATA 區段,請使用以下程式碼

<?php
$doc
= DOMDocument::loadXML('<node>old content</node>');
$node = $doc->getElementsByTagName('node')->item(0);
$node->removeChild($node->firstChild);
$newText = $doc->createCDATASection('new cdata content');
$node->appendChild($newText);
echo
"使用 CDATA 的內容: ".$doc->saveXML($node)."\n";
?>
19
R. Studer
14 年前
說明:
先前發文者所「發現」且看似未記載於文件中、用於此類別 (DOMNode) 的方法 ( .getElementsByTagName 和 .getAttribute ) 實際上是繼承自 DOMNode 的 DOMElement 類別的方法。

參見:https://php.dev.org.tw/manual/en/class.domelement.php
6
Steve K
15 年前
這個類別顯然也有一個 getElementsByTagName 方法。

我能夠透過使用 is_a() 函數對 DOMNodeList->item() 的輸出進行各種測試來確認這一點。
9
brian wildwoodassociates.info
15 年前
這個類別有一個 getAttribute 方法。

假設一個 DOMNode 物件 $ref 包含一個從 DOMNode List 中取出的錨點。那麼

$url = $ref->getAttribute('href');

會分離出與錨點的 href 部分相關聯的網址。
5
alastair dot dallas at gmail dot com
13 年前
關於混合內容的問題,我經過了一些實驗才想起來,所以我想添加這個註釋以節省其他人的時間。

當你的標記類似於:<div><p>第一個文字。</p><ul><li><p>第一個項目</p></li></ul></div> 時,你會得到相當規律的 XML_ELEMENT_NODE。<div> 的子節點是 <p> 和 <ul>,而兩個 <p> 的 nodeValue 都會產生你預期的文字。

但是,當你的標記更像是 <p>這是 <b>粗體</b>,這是 <i>斜體</i>。</p> 時,你會發現 XML_ELEMENT_NODE 的 nodeValue 並不可靠。在這種情況下,你需要查看 <p> 的子節點。在此範例中,<p> 的子節點是:#text、<b>、#text、<i>、#text。

在這個例子中,<b> 和 <i> 的 nodeValue 與它們的 #text 子節點相同。但是你可能會有這樣的標記:<p>這是 <b>粗體,<i>粗斜體</i></b>,看到了嗎?</p>。在這種情況下,你需要查看 <b> 的子節點,它們將是 #text、<i>,因為 <b> 的 nodeValue 並不充分。

XML_TEXT_NODE 沒有子節點,並且始終命名為 '#text'。根據空格的處理方式,你的樹可能在 <body> 和其他地方具有「空」的 #text 節點作為子節點。

屬性是節點,但我忘記了它們不在 childNodes 表示的樹中。使用 childNodes 遍歷整棵樹不會訪問任何屬性節點。
7
imranomar at gmail dot com
13 年前
剛發現 node->nodeValue 會去除所有標籤
2
metanull
10 年前
另一個將 DOMNode 轉換為 php 陣列的函數。
此頁面上的其他函數生成的陣列太「複雜」;這個函數應盡可能保持陣列的整潔。
注意:在呼叫 DOMDocument::load、loadXML 或 loadHTML 時,請確保設定 LIBXML_NOBLANKS
參見:http://be2.php.net/manual/en/libxml.constants.php
參見:http://be2.php.net/manual/en/domdocument.loadxml.php

<?php
/**
* 將 DOMNode 轉換成陣列
* 注意:載入 XML 到 DOMDocument 時,請務必使用 LIBXML_NOBLANKS 旗標
* @param DOMDocument $dom
* @param DOMNode $node
* @return array
*/
function nodeToArray( $dom, $node) {
if(!
is_a( $dom, 'DOMDocument' ) || !is_a( $node, 'DOMNode' )) {
return
false;
}
$array = false;
if( empty(
trim( $node->localName ))) {// 捨棄空節點
return false;
}
if(
XML_TEXT_NODE == $node->nodeType ) {
return
$node->nodeValue;
}
foreach (
$node->attributes as $attr) {
$array['@'.$attr->localName] = $attr->nodeValue;
}
foreach (
$node->childNodes as $childNode) {
if (
1 == $childNode->childNodes->length && XML_TEXT_NODE == $childNode->firstChild->nodeType ) {
$array[$childNode->localName] = $childNode->nodeValue;
} else {
if(
false !== ($a = self::nodeToArray( $dom, $childNode))) {
$array[$childNode->localName] = $a;
}
}
}
return
$array;
}
?>
2
pizarropablo at gmail dot com
10 年前
回覆給 alastair dot dallas at gmail dot com 關於 "#text" 節點的問題。
當結束標籤與下一個起始標籤之間存在空格或換行符號時,就會出現 "#text" 節點。

例如 "<data><age>10</age>[空格]<other>20</other>[空格]</data>"

"data" 的 childNodes 會有 4 個子節點
- age = 10
- #text = 空格
- other = 20
- #text = 空格
4
matt at lamplightdb dot co dot uk
15 年前
顯然還有一個 setAttribute 方法。

$node->setAttribute( 'attrName' , 'value' );
1
matej dot golian at gmail dot com
11 年前
以下是一個小函式,可以將 DomNode 截斷到指定的文字字元數。我用它來為我的部落格文章產生 HTML 摘要。

<?php

function makehtmlexcerpt(DomNode $html, $excerptlength)
{
$remove = 0;
$htmllength = strlen(html_entity_decode($html->textContent, ENT_QUOTES, 'UTF-8'));
$truncate = $htmllength - $excerptlength;
if(
$htmllength > $excerptlength)
{
if(
$html->hasChildNodes())
{
$children = $html->childNodes;
for(
$counter = 0; $counter < $children->length; $counter ++)
{
$child = $children->item($children->length - ($counter + 1));
$childlength = strlen(html_entity_decode($child->textContent, ENT_QUOTES, 'UTF-8'));
if(
$childlength <= $truncate)
{
$remove ++;
$truncate = $truncate - $childlength;
}
else
{
$child = makehtmlexcerpt($child, $childlength - $truncate);
break;
}
}
if(
$remove != 0)
{
for(
$counter = 0; $counter < $remove; $counter ++)
{
$html->removeChild($html->lastChild);
}
}
}
else
{
if(
$html->nodeName == '#text')
{
$html->nodeValue = substr(html_entity_decode($html->nodeValue, ENT_QUOTES, 'UTF-8'), 0, $htmllength - $truncate);
}
}
}
return
$html;
}

?>
-1
匿名
6 年前
如果具體屬性的文件中能提到某些屬性的唯讀狀態會很有幫助
"
ownerDocument

與此節點關聯的 DOMDocument 物件。

"
-1
zlk1214 at gmail dot com
8 年前
一個可以設定內部 HTML 且不會產生編碼錯誤的函式。$html 可以是損壞的內容,例如 "<a ID=id20>ssss"
function setInnerHTML($node, $html) {
removeChildren($node);
if (empty($html)) {
return;
}

$doc = $node->ownerDocument;
$htmlclip = new DOMDocument();
$htmlclip->loadHTML('<meta http-equiv="Content-Type" content="text/html;charset=utf-8"><div>' . $html . '</div>');
$clipNode = $doc->importNode($htmlclip->documentElement->lastChild->firstChild, true);
while ($item = $clipNode->firstChild) {
$node->appendChild($item);
}
}
To Top