【PHP8.x】DOMNotation::textContentプロパティの使い方
textContentプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
textContentプロパティは、DOMNotationクラスに属し、ノードのテキストコンテンツを保持するプロパティです。通常、このプロパティはDOMノードのテキスト情報を取得したり、設定したりするために使用されます。
しかしながら、DOMNotationクラスは、XML文書内で外部のリソースやアプリケーションを定義するために使われる、<!NOTATION ...>宣言を表す特別なノードです。このNOTATIONノードは、その性質上、子ノードや直接的なテキストコンテンツを持ちません。
このため、DOMNotationオブジェクトのtextContentプロパティにアクセスすると、常に空文字列("")が返されます。また、このプロパティに値を設定しようとした場合でも、DOMNotationノードはテキストを保持できないため、設定値は無視され、ノードの内容が変更されることはありません。この際、エラーも発生しません。
したがって、DOMNotationクラスにおけるtextContentプロパティは、テキストコンテンツを操作する目的では利用されません。主にXML文書の構造を解析する際に、NOTATION宣言の存在を確認するために参照されるプロパティと理解してください。
構文(syntax)
1<?php 2$dom = new DOMDocument(); 3$dom->loadXML('<!DOCTYPE root [<!NOTATION gif SYSTEM "image/gif">]><root/>'); 4$notation = $dom->notations->item(0); 5$textContentValue = $notation->textContent;
引数(parameters)
引数なし
引数はありません
戻り値(return)
string
DOMNotationオブジェクトのテキストコンテンツを文字列として返します。
サンプルコード
PHP DOMDocument textContentでHTMLテキスト取得
1<?php 2 3/** 4 * DOMDocumentとtextContentプロパティを使用して、 5 * HTML要素からテキストコンテンツを抽出するサンプルです。 6 */ 7function extractTextFromHtml(): void 8{ 9 // サンプルとなるHTML文字列を定義します。 10 // <div id="main-content">には、テキストとネストされた<strong>タグが含まれています。 11 $htmlString = <<<HTML 12<!DOCTYPE html> 13<html> 14<head> 15 <title>サンプルページ</title> 16</head> 17<body> 18 <h1>ようこそ</h1> 19 <div id="main-content"> 20 これは主要なコンテンツです。 21 <strong>この部分は強調されています。</strong> 22 テキストは続きます。 23 </div> 24</body> 25</html> 26HTML; 27 28 // DOMDocumentオブジェクトをインスタンス化します。 29 $dom = new DOMDocument(); 30 31 // HTML5の要素で警告が出ないように、libxmlのエラーを内部で処理するように設定します。 32 libxml_use_internal_errors(true); 33 // HTML文字列を読み込みます。 34 $dom->loadHTML($htmlString); 35 // エラーハンドリング設定を元に戻すことが推奨されます。 36 libxml_use_internal_errors(false); 37 38 // ID 'main-content' を持つ要素を取得します。 39 $element = $dom->getElementById('main-content'); 40 41 // textContentプロパティは、指定したノードとその子孫のテキストコンテンツを連結して返します。 42 // この際、HTMLタグはすべて除去されます。 43 if ($element) { 44 echo $element->textContent; 45 } 46} 47 48// 関数を実行します。 49extractTextFromHtml(); 50 51?>
このサンプルコードは、PHPのDOMDocumentクラスを利用してHTML文書を解析し、特定の要素からテキスト情報のみを抽出する方法を示しています。中心となるのはtextContentプロパティです。
まず、new DOMDocument()でオブジェクトを生成し、loadHTMLメソッドで文字列のHTMLを読み込みます。これにより、HTMLはプログラムで操作可能な階層構造(DOMツリー)に変換されます。次に、getElementByIdメソッドを使って、IDがmain-contentのdiv要素を取得します。
textContentプロパティは、この取得した要素(ノード)とその内部に含まれるすべての子孫要素から、テキストコンテンツを連結して一つの文字列として返します。このプロパティの最大の特徴は、HTMLタグ(例:<strong>)をすべて無視し、純粋なテキストだけを抽出する点です。このプロパティに引数はなく、戻り値はstring型の文字列です。
サンプルコードの実行結果では、div要素内のテキスト「これは主要なコンテンツです。」と、<strong>タグ内の「この部分は強調されています。」、そして「テキストは続きます。」が連結された文字列が出力されます。このようにtextContentは、Webページから特定の箇所の文章だけを取り出したい場合に非常に有効な機能です。
textContentプロパティは、HTMLタグをすべて取り除き、指定した要素とその子要素のテキストのみを連結して取得します。この際、ソースコード上の改行やインデントによる空白文字もテキストとして含まれる点に注意が必要です。また、getElementByIdは対象の要素が見つからない場合にnullを返すため、プロパティにアクセスする前に必ずif文などで存在確認を行ってください。これがないとエラーが発生します。loadHTMLで外部のHTMLを扱う際は、文字コードの違いによる文字化けが起きやすいため、事前にUTF-8へ変換するなどの対策を推奨します。
PHP DOM: nodeValue vs textContent
1<?php 2 3declare(strict_types=1); 4 5// nodeValue と textContent の違いを比較するためのXML文字列。 6// DTD部分で DOMNotation を定義し、ボディ部分で比較対象の DOMElement を定義します。 7$xmlString = <<<XML 8<?xml version="1.0" encoding="UTF-8"?> 9<!DOCTYPE root [ 10 <!NOTATION png SYSTEM "image/png"> 11]> 12<root> 13 <item> 14 Item Text 15 <!-- comment --> 16 <span> and Span Text</span> 17 </item> 18</root> 19XML; 20 21// DOMDocumentオブジェクトを生成し、XMLを読み込みます。 22$dom = new DOMDocument(); 23$dom->loadXML($xmlString); 24 25// --- 1. DOMNotation におけるプロパティの比較 --- 26// DOMNotationはDTD(文書型定義)で定義され、子ノードを持ちません。 27// そのため、nodeValueとtextContentはどちらもnullを返します。 28echo "--- DOMNotationの場合 ---\n"; 29$notation = $dom->doctype->notations->getNamedItem('png'); 30if ($notation instanceof DOMNotation) { 31 echo 'nodeValue: '; 32 var_dump($notation->nodeValue); // 出力: NULL 33 echo 'textContent: '; 34 var_dump($notation->textContent); // 出力: NULL 35} 36echo "\n"; 37 38// --- 2. DOMElement におけるプロパティの比較(違いが明確な例) --- 39// 比較のため、子ノードを持つ<item>要素を取得します。 40echo "--- DOMElementの場合 ---\n"; 41$element = $dom->getElementsByTagName('item')->item(0); 42if ($element instanceof DOMElement) { 43 // nodeValueは、要素ノード自体が持つ値です。要素の場合、これは常にnullです。 44 echo 'nodeValue: '; 45 var_dump($element->nodeValue); // 出力: NULL 46 47 // textContentは、そのノードとすべての子孫ノードのテキストコンテンツを連結して返します。 48 // コメントや要素タグは無視されます。 49 $textContent = preg_replace('/\s+/', ' ', $element->textContent); 50 echo 'textContent: '; 51 var_dump(trim($textContent)); // 出力: string(21) "Item Text and Span Text" 52} 53
PHPのDOMNotationクラスに属するtextContentプロパティは、DOMノードとそのすべての子孫ノードが持つテキスト情報を取得します。このプロパティに引数はなく、戻り値として文字列(string)を返します。
このサンプルコードは、よく似たnodeValueプロパティとtextContentプロパティの挙動の違いを、DOMNotationとDOMElementという2種類のノードで比較しています。
まずDOMNotationの場合、これはXML文書内で外部データの形式を宣言するもので、自身の中にテキストなどの子ノードを持ちません。そのため、textContentプロパティを参照しても取得すべきテキスト情報が存在せず、nodeValueプロパティと同様にnullが返されます。
一方、比較のために示されているDOMElement(<item>要素)のケースでは、両者の違いが明確になります。nodeValueは要素ノード自体にはテキスト値がないためnullを返します。それに対し、textContentは要素内のテキスト「Item Text」と、その子孫である<span>要素内のテキスト「and Span Text」を連結した文字列を返します。このようにtextContentは、コメントやタグは無視し、人間が読むテキスト部分をまとめて取得する際に便利なプロパティです。
nodeValueとtextContentは似ていますが、取得できる情報が異なります。nodeValueは要素ノード(Element)自体にはテキスト値がないためNULLを返します。一方、textContentは指定したノードとその全ての子孫ノードから、タグやコメントを除いたテキスト情報だけを連結して取得します。このため、画面に表示されるような文字列をまとめて抽出したい場合に非常に便利です。ただし、DOMNotationのように子ノードを持てない特殊なノードでは、どちらのプロパティもNULLを返す点に注意してください。取得したテキストには意図しない空白や改行が含まれることがあるため、trim関数などで整形してから利用するとより安全です。