【PHP8.x】Dom\Text::wholeTextプロパティの使い方
wholeTextプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『wholeTextプロパティは、現在のTextノードと、DOMツリー上で論理的に隣接するすべてのTextノードのテキスト内容を連結した文字列を保持する読み取り専用のプロパティです。XMLやHTML文書では、テキストが要素ノードやコメントノードなどを間に挟まずに連続している箇所でも、内部的に複数のTextノードに分割されて表現されることがあります。このプロパティは、そのような分割されたテキストノード群を、あたかも一つの連続したテキストであるかのようにまとめて取得するために使用されます。textContentプロパティがそのノード自身のテキストのみを返すのに対し、wholeTextプロパティは、そのノードの前後に直接つながっている他のTextノードやCDATASectionノードの内容もすべて結合した結果を返します。これにより、DOMNode::normalize()メソッドを呼び出してDOM構造を実際に変更することなく、文書内での見た目通りの連続したテキストデータを簡単に取得することが可能になります。
構文(syntax)
1<?php 2 3$html = "<p>ここは最初のテキストノードです。<!-- comment -->ここは次のテキストノードです。</p>"; 4 5$doc = new Dom\Document(); 6$doc->loadHTML($html); 7 8// 最初の <p> 要素の最初の子ノード (テキストノード) を取得します 9$textNode = $doc->getElementsByTagName('p')->item(0)->firstChild; 10 11// wholeTextプロパティにアクセスして、論理的に隣接するすべてのテキストノードの内容を取得します 12$fullText = $textNode->wholeText; 13 14echo $fullText; // "ここは最初のテキストノードです。ここは次のテキストノードです。" と出力されます 15 16?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
string
Dom\Text::wholeTextプロパティは、ノードのすべてのテキストコンテンツを連結した文字列を返します。
サンプルコード
PHP: Dom\Text::wholeTextでテキストが数字のみか判定する
1<?php 2 3/** 4 * Dom\Text クラスの wholeText プロパティを使用し、 5 * テキストノードの全文を取得して、それが数字のみで構成されているかを判定する関数。 6 * 7 * @param string $textContent テスト対象のテキストノードに設定する文字列。 8 * @return void 9 */ 10function checkTextNodeForDigits(string $textContent): void 11{ 12 // 新しいDOMドキュメントを作成します。 13 // Dom\Text オブジェクトは通常、Dom\Document のコンテキストで作成されます。 14 $dom = new Dom\Document(); 15 16 // テスト用の要素(例: <p>)を作成し、DOMツリーに追加します。 17 // これは Dom\Text ノードを親要素にアタッチするための準備です。 18 $paragraphElement = $dom->createElement('p'); 19 $dom->appendChild($paragraphElement); 20 21 // Dom\Text ノードを作成し、指定されたテキストを設定します。 22 $textNode = $dom->createTextNode($textContent); 23 24 // テキストノードを要素の子として追加します。 25 $paragraphElement->appendChild($textNode); 26 27 // Dom\Text オブジェクトの wholeText プロパティにアクセスし、テキストノードの全文を取得します。 28 // このプロパティは、論理的に連続するテキストノードの結合されたテキストを返します。 29 // (この単純な例では、単一のテキストノードのコンテンツそのものです。) 30 $fullText = $textNode->wholeText; 31 32 echo "元の設定テキスト: '{$textContent}'\n"; 33 echo "Dom\\Text::wholeText で取得されたテキスト: '{$fullText}'\n"; 34 35 // 取得したテキストが完全に数字(0-9)のみで構成されているかを判定します。 36 // ctype_digit() 関数は、文字列がすべて数字で、かつ空でない場合に true を返します。 37 if (ctype_digit($fullText)) { 38 echo "判定結果: テキストは数字のみで構成されています。\n"; 39 } else { 40 echo "判定結果: テキストは数字以外の文字を含んでいます。\n"; 41 } 42 43 echo "----------------------------------------\n"; 44} 45 46// サンプルコードの実行例 47 48// 1. 数字のみのテキスト 49checkTextNodeForDigits('1234567890'); 50 51// 2. 数字と文字が混在するテキスト 52checkTextNodeForDigits('Order ID: 12345'); 53 54// 3. 文字のみのテキスト 55checkTextNodeForDigits('HelloWorld'); 56 57// 4. 空のテキスト 58checkTextNodeForDigits(''); 59 60// 5. 負の数(ctype_digit はハイフンを数字とみなさないため false となる) 61checkTextNodeForDigits('-123'); 62 63// 6. 小数(ctype_digit はピリオドを数字とみなさないため false となる) 64checkTextNodeForDigits('123.45');
PHP 8のDom\Textクラスに存在するwholeTextプロパティは、HTMLやXML文書構造(DOM)の中で、テキストノードが保持するテキストコンテンツの全文を取得するために利用されます。このプロパティは引数を一切取らず、戻り値としてテキストノードの全文を文字列(string)型で返します。特に、複数のテキストノードが論理的に連続している場合、それらの内容を結合した一つのテキストとして取得できる点が特徴です。
提供されたサンプルコードのcheckTextNodeForDigits関数は、引数$textContentで指定された文字列を元にDom\Textノードを作成します。その後、$textNode->wholeTextという形でこのプロパティにアクセスし、テキストノードの全文を取得しています。この関数は戻り値がvoidであるため、値を返さずに処理結果を直接画面に出力します。取得したテキストに対しては、ctype_digit()関数を用いて、その内容が完全に数字(0-9)のみで構成されているかを判定しています。ctype_digit()関数は、文字列がすべて数字で、かつ空でない場合にtrueを返します。例えば、「12345」は数字のみと判定されますが、「Order ID: 12345」や「-123」、「123.45」のように数字以外の文字や記号が含まれる場合は、数字のみではないと判定されます。このようにwholeTextプロパティを使用することで、DOM内のテキストコンテンツを正確に抽出し、その内容に応じて特定の条件(例:数字のみか)を満たすかどうかの検証を行うことが可能です。
Dom\Text::wholeTextプロパティは、DOMのテキストノードから論理的に連続するテキストの全文を取得します。単一のテキストノードであれば、その内容そのままが取得されると理解してください。サンプルでは、取得したテキストが「数字のみ」かを判定するためにctype_digit()関数を使用していますが、この関数には注意点があります。ctype_digit()は、文字列が1文字以上の数字(0-9)のみで構成されている場合に限りtrueを返します。そのため、空文字列、負の数(ハイフンを含む)、小数(ピリオドを含む)、またはスペースなどの数字以外の文字が混じっている場合はfalseと判定されます。これらのケースも「数字」として扱いたい場合は、正規表現など、より柔軟な判定方法を検討すると良いでしょう。
PHP Dom\Text wholeText を while(true) で取得する
1<?php 2 3/** 4 * Dom\Text クラスの wholeText プロパティの使用例と while(true) ループを組み合わせた関数。 5 * 6 * この関数は、指定されたHTMLドキュメントからテキストノードを取得し、 7 * その wholeText プロパティの値を繰り返し表示します。 8 * while(true) ループは、特定の条件(ここではループ回数)が満たされたら break します。 9 * 10 * Dom\Text::wholeText は、DOMツリー内の連続するテキストノード(コメントノードなどを除く) 11 * 全てを結合した文字列を返します。これは単一ノードのテキストコンテンツを返す 12 * nodeValue とは異なります。 13 */ 14function demonstrateDomTextWholeText(): void 15{ 16 // DOMDocument オブジェクトを作成し、サンプルHTMLをロードします。 17 // LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD は、HTML解析時に 18 // 余計な <html>, <body>, <!DOCTYPE> タグの自動挿入を抑制します。 19 // @ を付けて警告を抑制していますが、実運用では適切なエラーハンドリングを推奨します。 20 @$doc = new DOMDocument(); 21 @$doc->loadHTML(' 22 <!DOCTYPE html> 23 <html> 24 <body> 25 <p> 26 最初のテキスト<!-- ここはコメント --> 27 そして 28 <a href="#">リンク</a> 29 継続するテキスト。 30 </p> 31 </body> 32 </html> 33 ', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); 34 35 // DOMXPath オブジェクトを作成し、HTMLドキュメントをクエリできるようにします。 36 $xpath = new DOMXPath($doc); 37 38 // 最初の <p> 要素の子であるテキストノードを全て取得します。 39 // このHTMLでは、"最初のテキスト" と "そして" と "継続するテキスト。" がそれぞれ異なるテキストノードとして認識されます。 40 // <a href="#">リンク</a> の部分は要素ノードのため、テキストノードの連続性を分断します。 41 $textNodes = $xpath->query('//p/text()'); 42 43 if ($textNodes->length > 0) { 44 // 最初のテキストノード("最初のテキスト")を取得します。 45 // PHP 8 では Dom\Text クラスが DOMText クラスの新しい名前空間化されたバージョンとして提供されています。 46 $firstTextTextNode = $textNodes->item(0); 47 48 // ループカウンターを初期化します。 49 $counter = 0; 50 51 // while(true) ループを開始します。無限ループですが、内部に break 条件を設定して終了させます。 52 while (true) { 53 echo "--- ループ回数: " . ($counter + 1) . " ---\n"; 54 55 // 取得したノードが Dom\Text のインスタンスであることを確認します。 56 if ($firstTextTextNode instanceof Dom\Text) { 57 // wholeText プロパティは、現在のテキストノードとその後に続く兄弟テキストノードを結合した文字列を返します。 58 // ここでは、"最初のテキスト" ノードの wholeText は "最初のテキスト" そのものになります。 59 // コメントノードはスキップされますが、要素ノードによってテキストの連続性が途切れるため、 60 // この例の "最初のテキスト" の後には連続するテキストノードが存在しません。 61 // (「そして」は別のテキストノードと判断される) 62 echo "取得した wholeText: '" . $firstTextTextNode->wholeText . "'\n"; 63 64 // 比較のために nodeValue も表示します。 65 // nodeValue は、そのノード自身のテキストコンテンツのみを返します。 66 // この場合、wholeText と nodeValue は同じ値を返します。 67 echo "取得した nodeValue (比較用): '" . $firstTextTextNode->nodeValue . "'\n"; 68 } else { 69 echo "エラー: 取得したノードは Dom\\Text インスタンスではありません。\n"; 70 break; // エラーの場合はループを終了 71 } 72 73 // ループカウンターをインクリメントします。 74 $counter++; 75 76 // ループを3回実行したら終了します。 77 if ($counter >= 3) { 78 echo "設定されたループ回数に達したため、ループを終了します。\n"; 79 break; // ループを中断します 80 } 81 82 // コマンドライン実行時の視覚的な区切りのための一時停止 (任意) 83 // sleep(1); 84 } 85 } else { 86 echo "指定されたHTMLからテキストノードを見つけることができませんでした。XPathクエリやHTML構造を確認してください。\n"; 87 } 88} 89 90// 関数を実行します。 91demonstrateDomTextWholeText();
このPHPサンプルコードは、PHP 8で導入されたDom\Textクラスが持つwholeTextプロパティと、while(true)ループの基本的な使用方法をシステムエンジニアを目指す初心者向けに紹介しています。
Dom\Text::wholeTextは、DOMツリー内のテキストノードに属するプロパティです。このプロパティに引数はなく、戻り値として結合された文字列を返します。その役割は、現在のテキストノードと、その後に続く連続した兄弟テキストノード(コメントノードや処理命令ノードなどを除く)のコンテンツをすべて結合し、一つの完全な文字列として取得することです。これは、特定のノード自身のテキストコンテンツのみを返すnodeValueとは異なり、複数の連続するテキスト部分を一括で扱いたい場合に有用です。ただし、要素ノードが途中に挟まるとテキストの連続性が途切れるため、このサンプルコードではwholeTextとnodeValueが同じ結果を返しています。
一方、while(true)は、その条件が常に真であるため、内部にbreak文などの明示的な脱出条件がなければ無限に繰り返されるループです。このサンプルコードでは、ループが設定された回数(3回)実行された時点で、break文によって意図的にループを終了させる方法を示しています。
コードは、まず指定されたHTMLドキュメントから特定のテキストノードを取得し、そのノードのwholeTextプロパティの値をwhile(true)ループ内で繰り返し表示します。これにより、wholeTextプロパティが返す値と、while(true)ループの制御の仕組みを同時に確認できます。
Dom\Text::wholeTextプロパティは、現在のテキストノードとその後に続く兄弟テキストノードを結合した文字列を返しますが、要素ノードが間に存在するとテキストの連続性が途切れる点に注意が必要です。単一のノード値のみを返すnodeValueとはこの点で異なります。while(true)ループは無限ループであるため、プログラムが停止しなくならないよう、必ず内部にbreak文による明確な終了条件を設定してください。DOMDocument::loadHTMLなどのHTML解析時にエラーが発生する可能性があるため、サンプルコードのように@で警告を抑制するのではなく、try-catch文や戻り値の確認による適切なエラーハンドリングを実装することが重要です。DOMツリーの構造やXPathクエリを理解することが、目的のテキストノードを正確に取得するために不可欠です。