PHP Conference Japan 2024

DOMDocument::getElementById

(PHP 5, PHP 7, PHP 8)

DOMDocument::getElementById搜尋具有特定 ID 的元素

說明

public DOMDocument::getElementById(字串 $elementId): ?DOMElement

此函式類似於 DOMDocument::getElementsByTagName,但會搜尋具有指定 ID 的元素。

要使此函式正常運作,您需要使用 DOMElement::setIdAttribute 設定一些 ID 屬性,或使用定義類型為 ID 的屬性的 DTD。在後一種情況下,您需要在使用此函式之前,使用 DOMDocument::validateDOMDocument::$validateOnParse 驗證您的文件。

參數

elementId

元素的唯一 ID 值。

回傳值

如果找到元素,則回傳 DOMElement;如果找不到,則回傳 null

範例

範例 #1 DOMDocument::getElementById() 範例

以下範例使用 book.xml,其內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE books [
  <!ELEMENT books   (book+)>
  <!ELEMENT book    (title, author+, xhtml:blurb?)>
  <!ELEMENT title   (#PCDATA)>
  <!ELEMENT blurb   (#PCDATA)>
  <!ELEMENT author  (#PCDATA)>
  <!ATTLIST books   xmlns        CDATA  #IMPLIED>
  <!ATTLIST books   xmlns:xhtml  CDATA  #IMPLIED>
  <!ATTLIST book    id           ID     #IMPLIED>
  <!ATTLIST author  email        CDATA  #IMPLIED>
]>
<?xml-stylesheet type="text/xsl" href="style.xsl"?>
<books xmlns="http://books.php/" xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <book id="php-basics">
    <title>PHP Basics</title>
    <author email="jim.smith@basics.php">Jim Smith</author>
    <author email="jane.smith@basics.php">Jane Smith</author>
    <xhtml:blurb><![CDATA[
<p><em>PHP Basics</em> provides an introduction to PHP.</p>
]]></xhtml:blurb>
  </book>
  <book id="php-advanced">
    <title>PHP Advanced Programming</title>
    <author email="jon.doe@advanced.php">Jon Doe</author>
  </book>
</books>
<?php

$doc
= new DomDocument;

// 我們需要在引用 ID 之前驗證文件
$doc->validateOnParse = true;
$doc->Load('book.xml');

echo
"ID 為 'php-basics' 的元素是: " . $doc->getElementById('php-basics')->tagName . "\n";

?>

上述範例將輸出:

The element whose id is 'php-basics' is: book

參見

新增註解

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

ed at edgiardina dot com
14 年前
請注意,如果您的 HTML 沒有包含 doctype 宣告,則 getElementById 將永遠回傳 null。
carl2088 at gmail dot com
15 年前
根據我的經驗,如果您已載入 HTML 文件,getElementById 似乎可以在沒有任何設定的情況下正常運作。但是,為了讓 getElementById 能夠處理您「建構」的簡單 XML 文件,您必須使用「xml:」前綴設定 ID,並在您建立的元素上使用 setIdAttribute,否則它將無法運作。請參閱以下範例,希望這可以節省一些人的挫折感。如果您已載入 XML 檔案,則您只需確保 ID 的屬性具有 xml: 前綴。但是,如果您開始附加 XML 文件,請不要忘記在 ID 名稱或這些元素上使用 setIdAttribute,否則當您嘗試尋找它們時,getElementById 將會回傳 null。

<?php

/* test.xml
<?xml version="1.0" encoding="utf-8"?>
<root>
<child xml:id="id_xxxxxx" status="partial">
<sub_child>Some Data</sub_child>
</child>
</root>
*/

$xmlDom = new DOMDocument('1.0', 'utf-8');
$xmlDom->formatOutput = true; // we want a nice output

// create a root
$eltRoot = $xmlDom->createElement("root");
$xmlDom->appendChild($eltRoot);

$eltChild = $xmlDom->createElement("child");
$eltRoot->appendChild($eltChild);

// add a id attribute
$attr = $xmlDom->createAttribute("xml:id"); // needs xml prefix or getElementById won't work
$eltChild->appendChild($attr);

/// create the text node and append to the created element
$tNode = $xmlDom->createTextNode("id_8120528");
$attr->appendChild($tNode);
$eltChild->setIdAttribute("xml:id", true); // VERY IMPORT or getElementById won't work

// add a id attribute
$attr = $xmlDom->createAttribute("status");
$eltChild->appendChild($attr);

/// create the text node and append to the created element
$tNode = $xmlDom->createTextNode("partial");
$attr->appendChild($tNode);

// add a subchild
$eltSub = $xmlDom->createElement("sub_child");
$eltChild->appendChild($eltSub);

$tNode = $xmlDom->createTextNode("Some Data");
$eltSub->appendChild($tNode);

$id = null;
$id = $xmlDom->getElementById("id_8120528");

assert ($id != null);

$strId = $id->getAttribute("xml:id"); // bug? empty
$strStatus = $id->getAttribute("status"); // this works!

assert ($id !=null);

$xmlDom->save("./_data/test.xml");

$xmlDom->load("./_data/test.xml"); // reloading fixes the problem

$nodeRoot = $xmlDom->getElementsByTagName("root");
if (
$nodeRoot->length > 0) {
$eltRoot = $nodeRoot->item(0);
}

assert($eltRoot != null);

$id = null;
$id = $xmlDom->getElementById("id_8120528");

assert ($id != null);

$strId = $id->getAttribute("xml:id"); // this works now!
$strStatus = $id->getAttribute("status"); // this works!


?>
paradox_haze at live dot de
14 年前
在 XHTML 文件中搜尋特定元素時,getElementById() 出現了一些問題。
我寫了一個小函式來解決我的問題

<?php
function getElementById($id)
{
$xpath = new DOMXPath($this->domDocument);
return
$xpath->query("//*[@id='$id']")->item(0);
}
?>
simon at somewhere dot com
17 年前
讓你省去一個大麻煩以及翻閱大量文件的时间 -

不要使用 $object->setAttribute('id', 'id_name_here')
請使用:$object->setAttribute('xml:id', 'id_name_here')

然後,要取得節點值:$domDocumentObject->getElementById('id_name_here');

xml:id 屬性應該會自動定義!!

哇!真是太簡單了......
bart at mediawave dot nl
19 年前
getElementById 似乎在沒有設定 validateOnParse 為 true 的情況下也能正常運作。這很棒,因為將它設定為 true 會導致我的腳本出現一些效能問題。
匿名
18 年前
如果您嘗試將 getElementById 用於根據 xsd 檔案驗證的 xml 檔案,則必須先使用 schemaValidate 函式,否則 getElementById 將返回 null。
範例

$dom = new DomDocument();
$dom->load("users.xml");
$dom->schemaValidate("users.xsd");

$curruser = $dom->getElementById($user->name);
Hoi
4 年前
要設定一個可供 $dom->getElementById() 使用的隱藏 id,請套用 setAttribute('id', true),如下例所示

$createItemNode = function ($data) use ($dom) {
$node = $dom->createElement("Item");
$node->setAttribute('id', $data->id);
$node->setAttribute('hed', $data->hed);
$node->setAttribute('run_time', $data->run_time);
$node->setAttribute('date', $data->date);

// 在內部將 id 標記為 'xml:id',以便 getElementById 運作。手動將 xml:id 新增至標籤會導致 loadXML 拋出錯誤 DOMDocument: xml:id is not a NCName in Entity
$node->setIdAttribute('id', true);

return $node;
};

使用 $node->setIdAttribute('id', true) 後,$dom->getElementById($id) 將會正常運作

當您執行 $dom->saveXML() 時,最終文件將不包含任何 xml:id 屬性。
Tangui dot Le-Pense at laposte dot net
18 年前
有時無法從 DTD 驗證文件以使用 getElementById(例如,當 XHtml 文件中尚未包含 head 和 body 元素時:驗證失敗)。
幸運的是,這個函式支援 xml:id :)
這可能很有用。
http://www.w3.org/TR/xml-id/
jonbarnett at gmail dot com
18 年前
如果您的 XML 文件沒有將 "id" 屬性定義為 ID 的 DTD,那麼最簡單的方法是使用 XPath->query() 來尋找符合 "//[@id='x']" 的元素。
guillaume dot crico at gmail dot com
16 年前
您不想使用「xml:id」嗎?
這裡有一個 relaxNG 的技巧(使用通用 schema)
(使用 libxml 2.6.26 測試)

<?php
$doc
= new DOMDocument();
$doc->load(...);

$rng = '
<grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<start>
<element>
<anyName/>
<ref name="anythingID"/>
</element>
</start>
<define name="anythingID">
<zeroOrMore>
<choice>
<element>
<anyName/>
<ref name="anythingID"/>
</element>
<attribute name="id">
<data type="ID"/>
</attribute>
<zeroOrMore>
<attribute><anyName/></attribute>
</zeroOrMore>
<text/>
</choice>
</zeroOrMore>
</define>
</grammar>
'
;

$doc->relaxNGValidateSource($rng);
var_dump($doc->getElementById('id1'));
?>


請注意,ID 值必須是有效的
- 整數無效!
- 參考 http://www.w3.org/TR/REC-xml/#id
- => (字母 | '_' | ':') ( 字母 | 數字 | '.' | '-' | '_' | ':' | 組合字元 | 擴展字元 )*
To Top