【PHP8.x】nodeValueプロパティの使い方

nodeValueプロパティの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

nodeValueプロパティは、Dom\CharacterDataクラスに所属するプロパティで、ノードの値を文字列として保持するプロパティです。Dom\CharacterDataクラスは、XMLドキュメントやHTMLドキュメントにおけるテキストノードやコメントノードなどの文字データを扱うための抽象クラスです。

このnodeValueプロパティは、これらの文字データノードが持つ実際のテキスト内容を表します。具体的には、テキストノードであればテキストそのもの、コメントノードであればコメントの内容、処理命令ノードであれば処理命令の内容がこのプロパティに格納されます。

nodeValueプロパティの値を取得することで、ノードに格納された文字データの内容を知ることができます。また、このプロパティに値を設定することで、ノードの値を変更することも可能です。

例えば、テキストノードのテキストを書き換えたり、コメントノードのコメント内容を修正したりする際に、このnodeValueプロパティを使用します。Dom\CharacterDataを継承した具体的なクラス(例えば、DOMTextクラスやDOMCommentクラス)のインスタンスに対して、nodeValueプロパティを操作することで、ドキュメントの内容を動的に変更することができます。

nodeValueプロパティは、XMLやHTMLドキュメントを解析・操作する上で非常に重要な役割を果たします。ドキュメントの構造を理解し、目的のノードにアクセスし、そのノードの値を操作することで、様々な処理を実現できます。Dom\CharacterDataクラスとその派生クラスを理解し、nodeValueプロパティを適切に利用することで、PHPによるXML/HTML処理の幅が広がります。

構文(syntax)

1Dom\CharacterData::$nodeValue;

引数(parameters)

引数なし

引数はありません

戻り値(return)

string|null

このプロパティは、ノードのテキストコンテンツを表す文字列、またはノードにテキストコンテンツがない場合は null を返します。

サンプルコード

PHP DOM nodeValueとtextContentの違いを比較する

1<?php
2
3/**
4 * Dom\CharacterData::nodeValue と Dom\Node::textContent の違いを比較する関数。
5 *
6 * システムエンジニアを目指す初心者向けに、異なる種類のDOMノードにおける
7 * nodeValue と textContent の振る舞いを明確に示します。
8 *
9 * - nodeValue: 主にテキストノード、コメントノード、CDATAセクションノードなど、
10 *              "値"を持つノードのコンテンツを取得・設定します。
11 *              要素ノードの場合、通常は null です。
12 * - textContent: ノードとそのすべての子孫ノードのテキストコンテンツを連結して取得・設定します。
13 *                要素ノードでよく使用され、その内部のすべてのテキストを抽出するのに便利です。
14 */
15function demonstrateNodeValueVsTextContent(): void
16{
17    $dom = new Dom\Document();
18    // HTML文字列をロード
19    // ここでは、要素ノード、テキストノード、コメントノードを含むDOM構造を作成します。
20    $html = <<<HTML
21    <div id="container">
22        <!-- この部分はコメントです -->
23        Hello <span>World</span>!
24        <p>PHP DOM の学習</p>
25    </div>
26    HTML;
27    $dom->loadHTML($html);
28
29    echo "--- Dom\Element (要素ノード: div#container) ---\n";
30    $divElement = $dom->getElementById('container');
31    // 要素ノードの nodeValue は通常 null です。
32    echo "nodeValue: " . var_export($divElement->nodeValue, true) . "\n";
33    // textContent は、要素とその子孫のテキストコンテンツをすべて結合したものです。
34    // コメントは textContent に含まれません。
35    echo "textContent: " . var_export($divElement->textContent, true) . "\n\n";
36
37    echo "--- Dom\Comment (コメントノード) ---\n";
38    // 最初のコメントノードを見つける
39    $commentNode = null;
40    foreach ($divElement->childNodes as $childNode) {
41        if ($childNode instanceof Dom\Comment) {
42            $commentNode = $childNode;
43            break;
44        }
45    }
46    if ($commentNode) {
47        // コメントノードの nodeValue はコメントの内容そのものです。
48        echo "nodeValue: " . var_export($commentNode->nodeValue, true) . "\n";
49        // コメントノードの textContent もコメントの内容そのものになります。
50        echo "textContent: " . var_export($commentNode->textContent, true) . "\n\n";
51    }
52
53    echo "--- Dom\Text (テキストノード: 'Hello ') ---\n";
54    // 'Hello 'というテキストノードを取得(loadHTMLは空白もテキストノードとして扱います)
55    $helloTextNode = null;
56    foreach ($divElement->childNodes as $childNode) {
57        if ($childNode instanceof Dom\Text && trim($childNode->nodeValue) === 'Hello') {
58            $helloTextNode = $childNode;
59            break;
60        }
61    }
62    // 上記では'Hello'と' World'が別のテキストノードになるため、ここでは直接的なテキストノードの例として
63    // より単純なケースを考えます。あるいは、親ノードの子をたどって正確なテキストノードを特定します。
64    // loadHTMLの挙動により、ここでは "Hello " と "World" が異なるテキストノードとして扱われる可能性が高いです。
65    // そのため、より確実に最初のテキストコンテンツを取得する方法を選びます。
66
67    // 'Hello' の部分のテキストノードは、<div>の最初の子孫テキストノードの一つです。
68    // DOMDocument::loadHTML は、ノード間に空白がある場合もテキストノードとして生成するため、
69    // 実際に「Hello」というテキストを持つノードを見つける必要があります。
70    // ここでは、divElementの子ノードを走査し、テキストノードを識別します。
71    $foundHelloTextNode = null;
72    foreach ($divElement->childNodes as $child) {
73        if ($child instanceof Dom\Text && str_contains($child->nodeValue, 'Hello')) {
74            $foundHelloTextNode = $child;
75            break;
76        }
77    }
78
79    if ($foundHelloTextNode) {
80        // テキストノードの nodeValue はそのテキストコンテンツです。
81        echo "nodeValue: " . var_export($foundHelloTextNode->nodeValue, true) . "\n";
82        // テキストノードの textContent もそのテキストコンテンツです。
83        echo "textContent: " . var_export($foundHelloTextNode->textContent, true) . "\n\n";
84    }
85
86    echo "--- Dom\Element (要素ノード: span) ---\n";
87    $spanElement = $dom->getElementsByTagName('span')->item(0);
88    if ($spanElement) {
89        // 要素ノードの nodeValue は null です。
90        echo "nodeValue: " . var_export($spanElement->nodeValue, true) . "\n";
91        // textContent は 'World' です。
92        echo "textContent: " . var_export($spanElement->textContent, true) . "\n\n";
93    }
94}
95
96// 関数を実行して結果を表示します。
97demonstrateNodeValueVsTextContent();

PHP 8におけるDOM操作では、ノードが持つテキストコンテンツを取得するためにDom\CharacterData::nodeValueDom\Node::textContentの二つのプロパティが主に利用されます。

nodeValueは、Dom\CharacterDataクラスのプロパティで、主にテキストノード、コメントノード、CDATAセクションノードのように、ノード自身が直接的な「値」を持つ場合のコンテンツを取得・設定する際に使用されます。このプロパティに引数はなく、文字列またはnullを返します。要素ノード(例えば<div><span>)の場合、nodeValueは通常nullとなります。

一方、textContentは、Dom\Nodeクラスのプロパティで、ノードとそのすべての子孫ノードが持つテキストコンテンツを連結して取得・設定する際に使用されます。こちらも引数はなく、文字列またはnullを返します。要素ノードの内部にあるすべてのテキストを一度に抽出したい場合に非常に便利ですが、通常、親要素のtextContentにはコメントノードの内容は含まれません。

このサンプルコードでは、Dom\DocumentにロードされたHTML内の要素ノード、コメントノード、テキストノードといった異なる種類のDOMノードに対して、nodeValuetextContentがどのような値を返すかを具体的に比較しています。この比較を通じて、要素ノードではnodeValuenullとなる一方でtextContentが子孫のテキストを結合する様子や、コメントノードやテキストノードでは両プロパティが類似の値を返すなど、それぞれのプロパティの特性と使い分けが明確に示されています。

要素ノードのnodeValueは通常nullとなるため、要素内のテキストを取得する際はtextContentを使用するのが一般的です。これは初心者の方が混同しやすい点ですのでご注意ください。textContentはノードとその子孫のテキスト内容を連結して返しますが、HTMLコメントノードのテキストは含まれません。コメント自体を取得したい場合は、コメントノードのnodeValueを利用します。テキストノードやコメントノードのようなデータを持つノードでは、nodeValuetextContentは多くの場合同じ値を返します。Dom\Document::loadHTML()はHTML内の改行や空白もテキストノードとして生成することがありますので、特定のテキストコンテンツを持つノードを確実に取得するには、コード中の探索ロジックのように注意深く子ノードを走査し、必要に応じてtrim()などで調整してください。