【PHP8.x】Dom\HTMLElement::nodeValueプロパティの使い方
nodeValueプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
nodeValueプロパティは、Dom\HTMLElementクラスに属し、DOMツリー内のノードが持つテキストデータを保持するプロパティです。このプロパティは、HTML文書の構造をプログラムから操作する際に利用されるDOM(Document Object Model)の基本的な要素の一つです。
しかし、Dom\HTMLElementのインスタンス、つまりHTMLの要素タグ(例えば<div>や<p>など)では、このnodeValueプロパティは通常nullを返します。これは、要素ノードそのものが直接的なテキストデータを持つのではなく、その子ノードとしてテキストコンテンツを保持するためです。
では、どのような場合にnodeValueが具体的な値を保持するのでしょうか。このプロパティは、要素ノードの子であるテキストノード(HTML内の純粋な文字列)やコメントノード、または属性ノードに対してアクセスした際に、そのノードの具体的なテキストコンテンツや値を保持します。例えば、あるHTMLElementの子として存在するテキストノードのnodeValueを参照することで、実際の文字列を取得したり、新しい文字列を代入して内容を変更したりすることが可能です。
したがって、Dom\HTMLElementの直接のnodeValueはnullですが、その子ノードや関連するノードをたどってnodeValueを使用することで、HTML文書内のより低レベルなテキスト情報を操作することが可能になります。要素ノードの内部にあるすべてのテキストコンテンツをまとめて取得したり設定したりする場合は、通常、より直感的に使えるtextContentプロパティを利用することが推奨されます。nodeValueは、ノードごとのテキストデータにアクセスする際に役立つ、DOM操作の基礎的なプロパティの一つです。
構文(syntax)
1<?php 2 3$dom = new DOMDocument(); 4$dom->loadHTML('<p id="myParagraph">最初のテキスト</p>'); 5 6$element = $dom->getElementById('myParagraph'); 7 8// nodeValue の取得 9$currentText = $element->nodeValue; 10 11// nodeValue の設定 12$element->nodeValue = '新しいテキスト'; 13 14?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
?string
Dom\HTMLElement::nodeValue は、ノードのテキストコンテンツを string 型で返します。ノードにテキストコンテンツがない場合や、ノードがテキストノード以外の場合は null を返します。
サンプルコード
PHP 8 DOM nodeValueを取得する
1<?php 2 3// PHP 8以降で利用可能な新しいDOM拡張を使用します。 4// Dom\Document は旧来の DOMDocument に代わる、よりモダンなDOM操作クラスです。 5use Dom\Document; 6use Dom\HTMLElement; 7 8/** 9 * 指定されたHTML文字列から特定のCSSセレクタに合致する最初の要素のnodeValueを返します。 10 * nodeValueは、要素自身とその全ての子孫ノードのテキストコンテンツを結合したものです。 11 * HTMLタグは取り除かれ、純粋なテキストが返されます。 12 * 13 * @param string $html HTMLソースコード文字列。 14 * @param string $selector 検索する要素を指定するCSSセレクタ (例: 'p', '#my-id', '.my-class')。 15 * @return string|null 指定されたセレクタに合致する要素のnodeValue、 16 * または要素が見つからない場合はnullを返します。 17 */ 18function getHTMLElementNodeValue(string $html, string $selector): ?string 19{ 20 // 新しいDom\Documentインスタンスを作成します。 21 $document = new Document(); 22 23 // HTML文字列をロードします。 24 // エラー報告を抑制するため@を使用しています。これにより、不正なHTMLがあっても 25 // PHPのエラーが発生せず、処理を続行できますが、本来はエラーハンドリングを 26 // きちんと実装することが推奨されます。 27 @$document->loadHTML($html); 28 29 // CSSセレクタを使用して、最初に合致する要素を検索します。 30 // querySelectorメソッドは、Dom\HTMLElementまたはDom\Elementのインスタンスを返します。 31 /** @var HTMLElement|null $element */ 32 $element = $document->querySelector($selector); 33 34 // 要素が見つかり、それが Dom\HTMLElement のインスタンスである場合、 35 // その nodeValue プロパティを返します。 36 if ($element instanceof HTMLElement) { 37 return $element->nodeValue; 38 } 39 40 // 要素が見つからなかった場合はnullを返します。 41 return null; 42} 43 44// --- 以下はサンプルコードの動作確認のための使用例です --- 45 46// 処理対象のHTML文字列を定義します。 47$sampleHtml = <<<HTML 48<!DOCTYPE html> 49<html> 50<head> 51 <title>サンプルページ</title> 52</head> 53<body> 54 <h1>ようこそ!</h1> 55 <p id="greeting">これは<b>PHP 8</b>のDOM拡張を使った<span style="color: blue;">サンプル</span>です。</p> 56 <div> 57 <p class="info">もっと情報が必要ですか?</p> 58 </div> 59</body> 60</html> 61HTML; 62 63// 1. IDセレクタを使って<p id="greeting">のnodeValueを取得する例 64$greetingNodeValue = getHTMLElementNodeValue($sampleHtml, '#greeting'); 65echo "ID 'greeting' のnodeValue: " . ($greetingNodeValue ?? '見つかりませんでした') . "\n"; 66// 期待される出力: "ID 'greeting' のnodeValue: これはPHP 8のDOM拡張を使ったサンプルです。" 67 68// 2. タグ名セレクタを使って<h1>のnodeValueを取得する例 69$h1NodeValue = getHTMLElementNodeValue($sampleHtml, 'h1'); 70echo "H1タグのnodeValue: " . ($h1NodeValue ?? '見つかりませんでした') . "\n"; 71// 期待される出力: "H1タグのnodeValue: ようこそ!" 72 73// 3. クラスセレクタを使って<p class="info">のnodeValueを取得する例 74$infoNodeValue = getHTMLElementNodeValue($sampleHtml, '.info'); 75echo "クラス 'info' のnodeValue: " . ($infoNodeValue ?? '見つかりませんでした') . "\n"; 76// 期待される出力: "クラス 'info' のnodeValue: もっと情報が必要ですか?" 77 78// 4. 存在しない要素のnodeValueを取得しようとする例 79$nonExistentNodeValue = getHTMLElementNodeValue($sampleHtml, 'footer'); 80echo "FOOTERタグのnodeValue: " . ($nonExistentNodeValue ?? '見つかりませんでした') . "\n"; 81// 期待される出力: "FOOTERタグのnodeValue: 見つかりませんでした" 82 83?>
このサンプルコードは、PHP 8から利用できる新しいDOM拡張機能を用いて、HTML要素のnodeValueプロパティの挙動を示すものです。Dom\HTMLElementクラスに所属するnodeValueプロパティは、引数を取らず、特定のHTML要素とその子孫要素に含まれる全てのテキストコンテンツを結合した純粋な文字列を戻り値として返します。この際、元のHTMLに含まれるタグや属性はすべて除去され、目に見えるテキスト部分のみが抽出されます。
具体的には、getHTMLElementNodeValue関数が、与えられたHTML文字列から指定されたCSSセレクタ(例: p, #my-idなど)に合致する最初の要素を検索します。要素が見つかりDom\HTMLElementのインスタンスであった場合、そのnodeValueプロパティの値が返されます。これにより、例えば<p id="greeting">これは<b>PHP 8</b>のDOM拡張を使った<span>サンプル</span>です。</p>のようなHTML要素からは、「これはPHP 8のDOM拡張を使ったサンプルです。」というテキストが取得されます。要素が見つからない場合はnullが戻り値となるため、安全に処理を続けることが可能です。サンプルコードの実行例では、異なるセレクタで複数の要素からnodeValueを取得し、その動作を確認しています。
Dom\HTMLElementのnodeValueは、要素とその全ての子孫ノードのテキストコンテンツを結合し、HTMLタグを取り除いた純粋なテキストを返します。タグは含まれませんので、HTML構造を保持したい場合は別のプロパティやメソッドを利用してください。サンプルコードはPHP 8以降の新しいDom拡張を使用しており、従来のDOMDocumentとは異なる動作やクラス構造です。Dom\Document::loadHTML()でエラー抑制@を使用していますが、本番環境ではエラーハンドリングを適切に実装し、不正なHTMLへの耐性を高めることが推奨されます。また、querySelector()は見つからない場合にnullを返すため、必ず戻り値がDom\HTMLElementのインスタンスであるかを確認する処理が必要です。nodeValueの戻り値型は?stringのため、nullになる可能性を常に考慮したコードを記述してください。
PHP DOM nodeValue vs textContentの比較
1<?php 2 3// PHP 8 の新しい DOM 拡張機能を使用します。 4// Dom\HTMLElement クラスは Dom\Element を継承しており、nodeValue プロパティと textContent プロパティを持ちます。 5use Dom\Document; 6use Dom\Node\Element as DomElement; // PHP 8.1以降のDOM名前空間変更に対応 7 8/** 9 * DOM 要素における nodeValue と textContent の違いをデモンストレーションします。 10 * 11 * システムエンジニアを目指す初心者向けに、それぞれのプロパティが 12 * どのようなテキスト内容を返すかを具体的に示します。 13 */ 14function demonstrateNodeValueVsTextContent(): void 15{ 16 // 比較対象となるHTML文字列を定義します。 17 // コメントノードやネストされた要素を含めることで、違いが明確になります。 18 $html = <<<HTML 19 <!DOCTYPE html> 20 <html> 21 <body> 22 <div id="parent-div"> 23 これは 24 <span>子要素のテキスト</span> 25 と 26 <!-- コメントは無視されます --> 27 <p>別の要素のテキスト</p> 28 です。 29 </div> 30 <p id="simple-text-node">純粋なテキストを持つ要素。</p> 31 <span id="empty-span"></span> 32 </body> 33 </html> 34 HTML; 35 36 // Dom\Document オブジェクトを作成し、HTMLをパースします。 37 $dom = new Document(); 38 // HTMLパーサーのエラーを抑制します。 39 @$dom->loadHtml($html); 40 41 // --- 1. 複数の子ノードを含む要素の場合 --- 42 // idが "parent-div" の要素を取得します。 43 // querySelector は Dom\Element (Dom\HTMLElement 相当) のインスタンスを返します。 44 $parentDiv = $dom->querySelector('#parent-div'); 45 46 if ($parentDiv instanceof DomElement) { 47 echo "--- 要素 (id: parent-div, 複数の子ノードを含む) ---\n"; 48 49 // nodeValue: 50 // 要素ノード (Dom\HTMLElement) の nodeValue は、DOM 標準では通常 null です。 51 // PHP の DOM 実装では、直接の子がテキストノードのみの場合にそのテキストを返すことがありますが、 52 // 複雑な子ノード構造を持つ要素では null を返すか、最初の直接の子テキストノードの値を返すことが多いです。 53 // この例では null になる可能性が高いです。 54 echo "nodeValue: " . var_export($parentDiv->nodeValue, true) . "\n"; 55 56 // textContent: 57 // 要素とそのすべての子孫ノードのテキストコンテンツを連結した文字列を返します。 58 // HTMLタグやコメントノードは無視されます。 59 echo "textContent: " . var_export($parentDiv->textContent, true) . "\n\n"; 60 } 61 62 // --- 2. 純粋なテキストのみを子として持つ要素の場合 --- 63 // idが "simple-text-node" の要素を取得します。 64 // この要素は主に単一のテキストノードを子として持ちます。 65 $simpleTextNodeElement = $dom->querySelector('#simple-text-node'); 66 67 if ($simpleTextNodeElement instanceof DomElement) { 68 echo "--- 要素 (id: simple-text-node, 純粋なテキストのみを含む) ---\n"; 69 70 // nodeValue: 71 // この場合、要素が直接テキストノードのみを子として持つため、 72 // そのテキストノードの値が nodeValue として返されることが多いです。 73 echo "nodeValue: " . var_export($simpleTextNodeElement->nodeValue, true) . "\n"; 74 75 // textContent: 76 // こちらも要素のテキスト内容を返します。 77 // このケースでは nodeValue と同じになる傾向があります。 78 echo "textContent: " . var_export($simpleTextNodeElement->textContent, true) . "\n\n"; 79 } 80 81 // --- 3. 子を持たない空の要素の場合 --- 82 // idが "empty-span" の要素を取得します。 83 $emptySpan = $dom->querySelector('#empty-span'); 84 85 if ($emptySpan instanceof DomElement) { 86 echo "--- 要素 (id: empty-span, 子を持たない空の要素) ---\n"; 87 88 // nodeValue: 89 // 子ノードがないため、null を返します。 90 echo "nodeValue: " . var_export($emptySpan->nodeValue, true) . "\n"; 91 92 // textContent: 93 // 子孫ノードがないため、空文字列を返します。 94 echo "textContent: " . var_export($emptySpan->textContent, true) . "\n\n"; 95 } 96 97 // --- 4. 純粋なテキストノード自体のプロパティ --- 98 // "これは" というテキストノードを取得します。 99 // parentDiv の最初の子ノードがテキストノードであることを前提としています。 100 $firstTextChild = $parentDiv ? $parentDiv->firstChild : null; 101 // 最初の有効なテキストノードを見つけるまでスキップします 102 while ($firstTextChild && $firstTextChild->nodeType !== XML_TEXT_NODE) { 103 $firstTextChild = $firstTextChild->nextSibling; 104 } 105 106 if ($firstTextChild) { 107 echo "--- 純粋なテキストノード (\"これは\") ---\n"; 108 109 // nodeValue: 110 // テキストノードの場合、そのノードが保持する生のテキストデータを返します。 111 echo "nodeValue: " . var_export($firstTextChild->nodeValue, true) . "\n"; 112 113 // textContent: 114 // テキストノードの場合、nodeValue と同じ値を返します。 115 echo "textContent: " . var_export($firstTextChild->textContent, true) . "\n\n"; 116 } 117} 118 119// 関数を実行してデモンストレーションを開始します。 120demonstrateNodeValueVsTextContent();
PHP 8のDom\HTMLElementクラスが持つnodeValueプロパティは、DOM要素の「値」を取得する際に用いられます。このプロパティに引数はなく、文字列またはnullを返します。Dom\HTMLElementのような要素ノードの場合、DOM標準では通常nullを返しますが、PHPのDOM実装では直接の子ノードがテキストノードのみの場合にそのテキストを返すことがあります。しかし、子ノードに別のHTMLタグなどが含まれる複雑な構造の場合、多くはnullとなります。
これに対し、textContentプロパティは、要素とその全ての子孫ノードに含まれるテキストコンテンツを連結した文字列を返します。HTMLタグやコメントノードは完全に無視されるため、要素内の目に見える全てのテキストを取得したい場合に適しています。
例えば、<div id="parent-div">テキスト<span>子要素</span>です</div>のような要素では、nodeValueは通常nullを返しますが、textContentは「テキスト子要素です」という文字列を返します。一方、<p>純粋なテキスト</p>のように直接テキストのみを持つ要素の場合、nodeValueとtextContentは同じ「純粋なテキスト」を返す傾向があります。また、子ノードを持たない空の要素では、nodeValueはnull、textContentは空文字列を返します。これらの違いを理解することで、HTML構造から適切なテキストを正確に抽出できるようになります。
Dom\HTMLElementのような要素ノードからテキスト内容を取得する際、nodeValueプロパティは通常nullを返すため、期待通りの結果が得られないことが多いです。要素とその子孫ノード全てのテキストコンテンツを結合して取得したい場合は、textContentプロパティを使用してください。textContentはHTMLタグやコメントノードを無視し、要素内の純粋なテキスト部分だけを連結して返します。
一方、nodeValueは、テキストノード自体が持つテキストデータや、属性ノードの値を取得する際に利用するのが適切です。初心者の方が要素内のテキスト取得で迷った場合は、まずtextContentの利用を検討すると安全で確実です。このサンプルコードはPHP 8以降の新しいDOM拡張機能に基づいています。