【PHP8.x】Dom\Notation::textContentプロパティの使い方
textContentプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
textContentプロパティは、PHPのDom\Notationオブジェクトのテキストコンテンツを保持するプロパティです。Dom\Notationクラスは、XMLドキュメントのDOCTYPE宣言内で定義される「表記法(Notation)」という概念を表現します。表記法は、XMLの外部に存在するデータ(例えば、特定の画像フォーマットやアプリケーションデータなど)を識別し、その形式を宣言するために利用されますが、それ自体が直接的なテキストデータを持つことはありません。
このtextContentプロパティは、通常、指定されたノードとその子孫ノードのすべてのテキスト内容を連結した文字列を返します。しかし、Dom\Notationノードは、その性質上、テキストノードのような実質的なテキストコンテンツを持つことがありません。そのため、Dom\NotationオブジェクトからこのtextContentプロパティを読み取ると、常に空の文字列が返されます。このプロパティに値を設定しようとしても、効果はありません。
Dom\Notationオブジェクトが実際に持つ重要な情報(例えば、表記法の名前、公開識別子、システム識別子など)は、このtextContentプロパティではなく、nodeName、publicId、systemIdといった別のプロパティを通じてアクセスすることができます。このプロパティはPHP 8以降で利用可能な新しいDOM拡張機能の一部であり、XMLドキュメント構造をプログラムから操作する際に活用されます。Dom\NotationノードのtextContentプロパティは常に空文字列を返すという特性を理解しておくことが、正確なXML処理を行う上で重要です。
構文(syntax)
1<?php 2 3$dom = new DOMDocument(); 4$dom->loadXML('<!DOCTYPE root [<!NOTATION gif SYSTEM "image/gif">]><root/>'); 5 6$doctype = $dom->doctype; 7$notation = $doctype->notations->getNamedItem('gif'); 8 9$content = $notation->textContent; 10 11?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
string
textContent プロパティは、DOMノードに含まれるすべてのテキストコンテンツを連結した文字列を返します。
サンプルコード
PHP DOMDocument textContentの利用
1<?php 2 3/** 4 * Dom\Notation クラスの textContent プロパティの使用例を示します。 5 * 6 * この関数は、DTD(文書型定義)を含むXMLをパースし、 7 * そこから特定の記法(Notation)ノードを取得します。 8 * Dom\Notation の textContent プロパティは、仕様上常に null を返すため、 9 * そのことを確認するコードとなっています。 10 * 11 * @return void 12 */ 13function showDomNotationTextContentExample(): void 14{ 15 // DTD内で記法(NOTATION)を宣言したXML文字列を定義します。 16 // ここでは 'jpeg' という名前の記法を宣言しています。 17 $xmlString = <<<XML 18 <?xml version="1.0" encoding="UTF-8"?> 19 <!DOCTYPE root [ 20 <!NOTATION jpeg PUBLIC "image/jpeg"> 21 ]> 22 <root/> 23 XML; 24 25 // DOMDocumentオブジェクトをインスタンス化します。 26 $doc = new DOMDocument(); 27 28 // XML文字列を読み込み、パースします。 29 $doc->loadXML($xmlString); 30 31 // 文書型定義(DOMDocumentType)ノードを取得します。 32 $doctype = $doc->doctype; 33 34 // DTD内に宣言されている記法(DOMNotation)の一覧を取得します。 35 // getNamedItemメソッドで、指定した名前の記法ノードを取得できます。 36 $notation = $doctype->notations->getNamedItem('jpeg'); 37 38 // DOMNotationオブジェクトのプロパティを確認します。 39 if ($notation instanceof DOMNotation) { 40 echo 'Public ID: ' . $notation->publicId . PHP_EOL; 41 42 // Dom\Notation::textContent は常に null を返します。 43 // なぜなら、記法ノードは子ノードを持つことができないからです。 44 echo 'textContent: '; 45 var_dump($notation->textContent); 46 } 47} 48 49// 関数を実行して結果を表示します。 50showDomNotationTextContentExample(); 51 52?>
このPHPサンプルコードは、XMLの文書型定義(DTD)内で宣言された「記法(Notation)」を表すDom\NotationクラスのtextContentプロパティの動作を解説するものです。
コードでは、まず<!NOTATION>を使ってjpegという記法を定義したXML文字列を用意します。記法とは、XML文書が参照する画像ファイルのような、XML以外のデータ形式を指定するための仕組みです。次に、DOMDocumentクラスを使ってこのXMLを解析し、doctypeプロパティから記法の一覧を取得します。そしてgetNamedItem('jpeg')メソッドで、目的のDOMNotationオブジェクトを取り出します。
このコードの重要な点は、$notation->textContentの部分です。textContentプロパティは通常、そのノードと全ての子ノードのテキストを連結した文字列を返しますが、DOMNotationノードは仕様上、子ノードを持つことができません。そのため、Dom\NotationのtextContentプロパティは引数を持たず、アクセスすると常にnullを返します。実行結果でvar_dump()の出力がNULLとなるのは、この仕様通りの挙動を示しています。
Dom\Notation クラスの textContent プロパティは、仕様上常に null を返します。これは、記法(Notation)が文書内のテキストを持つ要素ではなく、DTDで外部データの形式を定義するための特殊なノードであり、子ノードを持つことができないためです。したがって、このプロパティからテキスト内容を取得しようとしても値は得られません。DOMNotation オブジェクトを正しく取得するには、サンプルコードのようにXML文書内にDTDと <!NOTATION ...> 宣言が必要です。この宣言がないXMLを扱う場合、対象のノードが見つからずエラーの原因となる点にご注意ください。また、DOMDocument などのクラスを利用するには、PHPの dom 拡張が有効になっている必要があります。
PHP DOM: nodeValue と textContent の違いを比較する
1<?php 2 3declare(strict_types=1); 4 5/** 6 * DOMNode のプロパティである nodeValue と textContent の違いを比較します。 7 * 8 * `nodeValue` はノードの種類によって挙動が異なります。 9 * 例えば、要素ノード (DOMElement) の場合は常に null を返しますが、 10 * テキストノード (DOMText) の場合はそのテキスト内容を返します。 11 * 12 * 一方、`textContent` は、そのノードとすべての子孫ノードから 13 * タグやコメントを除いたテキストコンテンツを連結して返します。 14 * 15 * このサンプルでは、特定の要素ノードを取得し、 16 * 両方のプロパティの値を出力することで、その違いを明確にします。 17 */ 18function compareNodeValueAndTextContent(): void 19{ 20 // 比較用のシンプルなXML文字列を定義 21 $xmlString = <<<XML 22 <?xml version="1.0" encoding="UTF-8"?> 23 <article> 24 <title>nodeValue vs textContent</title> 25 <content> 26 これは <b>重要</b> なテキストです。<!-- コメントは無視されます --> 27 </content> 28 </article> 29 XML; 30 31 // DOMDocumentオブジェクトを作成し、XMLを読み込む 32 $dom = new DOMDocument(); 33 $dom->loadXML($xmlString); 34 35 // <content> 要素ノードを取得 (DOMElement) 36 // getElementsByTagNameはDOMNodeListを返すため、最初の要素を取得する 37 $contentElement = $dom->getElementsByTagName('content')->item(0); 38 39 // --- 比較 --- 40 echo '--- <content> 要素ノード (DOMElement) に対する比較 ---' . PHP_EOL; 41 42 // 1. nodeValue の値を出力 43 // DOMElement の場合、nodeValue は常に null となります。 44 // 子要素のテキストにはアクセスできません。 45 echo 'nodeValue: '; 46 var_dump($contentElement->nodeValue); // 出力: NULL 47 48 // 2. textContent の値を出力 49 // textContent は、子孫ノードのテキストをすべて連結して返します。 50 // <b>タグやコメントは無視され、テキスト部分のみが抽出されます。 51 echo 'textContent: '; 52 var_dump($contentElement->textContent); // 出力: string(56) " 53 // これは 重要 なテキストです。 54 // " 55 // trim() を使うと前後の空白を除去できます。 56 echo 'trim(textContent): '; 57 var_dump(trim($contentElement->textContent)); // 出力: string(45) "これは 重要 なテキストです。" 58} 59 60// 関数を実行して結果を表示 61compareNodeValueAndTextContent();
textContentプロパティは、指定したHTML/XMLのノード(要素)とその内部に含まれるすべての子孫ノードから、人間が読むテキスト部分だけを抽出して、一つの文字列として取得する機能を提供します。このプロパティに引数はなく、戻り値は取得したテキストコンテンツを表す文字列(string型)です。
よく似た機能を持つnodeValueプロパティとの違いが重要です。nodeValueはノードの種類によって挙動が異なり、サンプルコードにある<content>のような「要素ノード」に対して使用するとnullを返します。これは、要素自体が直接的なテキスト値を持たないためです。
一方、textContentは要素ノードに対して使用しても、その内部にあるテキストを再帰的にすべて探し出し、タグやコメントを除外した上で連結した文字列を返します。サンプルコードでは、<content>要素のtextContentを取得することで、<b>タグやHTMLコメントが取り除かれ、「これは 重要 なテキストです。」という純粋なテキストデータが取得できていることがわかります。このようにtextContentは、構造の中から表示されているテキスト全体を一度に取得したい場合に非常に便利なプロパティです。
PHPでXMLやHTMLの要素からテキストを取得する際、nodeValueとtextContentの使い分けが重要です。<p>タグのような要素自体からテキストを取り出そうとしてnodeValueを使うと、nullが返ってきてしまいます。これは、nodeValueが要素ノードに対しては機能しないためで、初心者がつまずきやすい点です。
要素とその内部に含まれる全てのテキストをまとめて取得したい場合は、textContentを使いましょう。textContentは、ネストされたタグやコメントを無視し、人間が読むのと同じようにテキスト部分だけを連結して返してくれます。ただし、取得した文字列には、元のコードのインデントによる空白や改行が含まれることがあるため、trim()関数などで不要な空白を除去すると、より意図したデータとして扱うことができます。