【PHP8.x】entitiesプロパティの使い方
entitiesプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
entitiesプロパティは、PHPのDOMDocumentTypeクラスに属し、XMLまたはHTMLドキュメントのDOCTYPE宣言内で定義されている、エンティティ宣言の情報を保持するプロパティです。
DOCTYPE宣言は、ドキュメントのタイプや構造に関する情報を提供するものであり、その中にエンティティが定義されることがあります。エンティティとは、特定の文字や文字列に名前を付け、ドキュメント内でその名前を使って参照できるようにする仕組みです。例えば、特殊文字や繰り返し使用されるテキストブロックを簡潔に表現するために利用されます。
このentitiesプロパティにアクセスすることで、ドキュメントタイプに定義されたすべてのエンティティ宣言を、DOMNamedNodeMapというオブジェクトとして取得できます。DOMNamedNodeMapは、名前と値のペアでノードを格納するコレクションであり、このケースではエンティティの名前をキーとして、個々のエンティティ宣言を表すDOMEntityオブジェクトが格納されています。
プロパティは読み取り専用であり、ドキュメントの既存のエンティティ情報を参照するために使用されますが、新しいエンティティを追加したり、既存のエンティティを変更したりすることはできません。システムエンジニアを目指す初心者の方にとっては、XMLドキュメントをパースし、その構造をプログラムから理解・操作する際に、特定の定義情報を取得するために役立つでしょう。
構文(syntax)
1<?php 2$document = new DOMDocument(); 3$document->loadXML('<!DOCTYPE root [<!ENTITY example "This is an example entity">]><root/>'); 4$doctype = $document->doctype; 5$entities = $doctype->entities; 6?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
DOMNamedNodeMap
DOMDocumentTypeクラスのentitiesプロパティは、このドキュメントタイプで宣言されている外部一般エンティティのコレクションをDOMNamedNodeMapオブジェクトとして返します。
サンプルコード
PHP: DOMDocumentTypeのentitiesでエンティティを取得する
1<?php 2 3/** 4 * DOMDocumentTypeのentitiesプロパティを使い、DTDで定義されたエンティティ情報を取得します。 5 * 6 * XMLドキュメント内のエンティティ参照がどのように展開(デコード)されるかを示すサンプルです。 7 */ 8function displayDocumentEntities(): void 9{ 10 // DTD (文書型定義) を含むXML文字列を準備します。 11 // <!ENTITY ...> 構文で、'author' と 'company' という2つのエンティティを定義しています。 12 $xmlString = <<<XML 13<?xml version="1.0" encoding="UTF-8"?> 14<!DOCTYPE note [ 15 <!ENTITY author "Taro Yamada"> 16 <!ENTITY company "PHP Corporation"> 17]> 18<note> 19 <author_name>&author;</author_name> 20 <company_name>&company;</company_name> 21 <description> 22 &author; は &company; に所属しています。 23 </description> 24</note> 25XML; 26 27 // DOMDocument オブジェクトを生成します。 28 $dom = new DOMDocument(); 29 30 // XML文字列を読み込みます。 31 // 第2引数に LIBXML_NOENT を指定すると、XML内のエンティティ参照 (&author; など) が 32 // DTDで定義された値 ('Taro Yamada' など) に置換(デコード)されます。 33 $dom->loadXML($xmlString, LIBXML_NOENT); 34 35 // doctypeプロパティからDOMDocumentTypeオブジェクトを取得します。 36 // これにはDTDの情報が含まれています。 37 $docType = $dom->doctype; 38 39 // DTDが存在しない場合は、メッセージを表示して終了します。 40 if ($docType === null) { 41 echo "DTD (Document Type Definition) が見つかりません。\n"; 42 return; 43 } 44 45 // entitiesプロパティは、DTDで定義された全エンティティを 46 // DOMNamedNodeMapオブジェクトとして返します。 47 $entities = $docType->entities; 48 49 echo "--- DTDで定義されたエンティティの一覧 ---\n"; 50 51 // DOMNamedNodeMapをループ処理して、各エンティティの情報を表示します。 52 // $entityはDOMEntityオブジェクトです。 53 foreach ($entities as $entity) { 54 // nodeName はエンティティ名 (例: 'author') 55 // textContent はエンティティの値 (例: 'Taro Yamada') 56 printf( 57 "エンティティ名: %-10s | 値: %s\n", 58 $entity->nodeName, 59 $entity->textContent 60 ); 61 } 62 63 echo "\n--- エンティティが展開(デコード)されたXMLノードの値 ---\n"; 64 65 // getElementsByTagNameでノードを取得し、エンティティが値に置き換わっていることを確認します。 66 $authorNode = $dom->getElementsByTagName('author_name')->item(0); 67 echo "author_nameタグの値: " . $authorNode->textContent . "\n"; // "Taro Yamada" が表示される 68 69 $companyNode = $dom->getElementsByTagName('company_name')->item(0); 70 echo "company_nameタグの値: " . $companyNode->textContent . "\n"; // "PHP Corporation" が表示される 71} 72 73// 関数を実行します。 74displayDocumentEntities();
PHPのDOMDocumentType::entitiesプロパティは、XML文書の文書型定義(DTD)内で定義されたエンティティの情報を取得するために使用されます。このプロパティは引数を取らず、戻り値としてDOMNamedNodeMapオブジェクトを返します。DOMNamedNodeMapは、DTDで定義された複数のエンティティ(それぞれがDOMEntityオブジェクト)の集合を管理しており、各エンティティの名前や値を簡単に参照できます。
サンプルコードでは、まずDTDにauthorやcompanyといったエンティティを定義したXML文字列を準備しています。このXMLをDOMDocument::loadXMLメソッドで読み込む際、第二引数にLIBXML_NOENTを指定することが重要です。このフラグを立てることで、XMLドキュメント内のエンティティ参照(例えば &author;)が、DTDで定義された実際の値(例: "Taro Yamada")に自動的に展開(デコード)されます。
その後、DOMDocumentオブジェクトのdoctypeプロパティからDOMDocumentTypeオブジェクトを取得し、そのentitiesプロパティにアクセスすることで、DTDで定義された全てのエンティティの一覧を取得しています。この一覧をループ処理することで、各エンティティの名前とその展開後の値を確認できます。また、エンティティが展開されたXMLノードのtextContentを取得する部分では、&author;のような参照が既に"Taro Yamada"という具体的な値にデコードされていることが示され、このプロパティとLIBXML_NOENTフラグの組み合わせが、エンティティ処理にどのように役立つかを理解できます。
このサンプルコードで重要なのは、DOMDocument::loadXMLにLIBXML_NOENTフラグを指定している点です。これにより、XML内の&author;のようなエンティティ参照がDTDで定義された値に自動的に展開(デコード)されます。
DOMDocumentType::entitiesプロパティは、XMLのDTD内で明示的に定義されたエンティティのみをDOMNamedNodeMapとして返します。&のような一般的な組み込みエンティティや、DTDに定義されていないエンティティはここには含まれませんのでご注意ください。
また、LIBXML_NOENTフラグの使用は、XML外部エンティティ(XXE)攻撃のリスクを高める可能性があります。信頼できないソースからのXMLを処理する際には、このフラグの使用を避けるか、適切なセキュリティ対策を講じることを強く推奨します。
PHP DOMDocumentType entities を取得する
1<?php 2 3/** 4 * DTD (Document Type Definition) に定義されたエンティティの情報を表示します。 5 * 6 * この関数は、HTML/XMLドキュメントのDTDからエンティティ定義(例: `<!ENTITY myEntity "value">`)を読み込み、 7 * その情報を出力します。これは、テキスト内のHTML特殊文字エンティティ(例: `&`)を 8 * デコード(削除)する一般的な処理とは異なります。 9 * 10 * @param string $documentContent DTDを含むHTMLまたはXMLの文字列。 11 * @return void 12 */ 13function displayDocumentTypeEntities(string $documentContent): void 14{ 15 $dom = new DOMDocument(); 16 // HTMLコンテンツをロード。DTD関連のエラーを避けるため抑制します。 17 @$dom->loadHTML($documentContent); 18 19 // ドキュメントタイプノードを取得します。 20 $doctype = $dom->doctype; 21 22 if ($doctype instanceof DOMDocumentType) { 23 echo "ドキュメントタイプに定義されているエンティティ:\n"; 24 25 // DOMDocumentType::entities は、DTDに定義されたエンティティのマップを取得します。 26 // これはDOMNamedNodeMapオブジェクトで、各要素はDOMEntityです。 27 $entities = $doctype->entities; 28 29 if ($entities->length > 0) { 30 foreach ($entities as $entity) { 31 if ($entity instanceof DOMEntity) { 32 echo " - 名前: " . $entity->nodeName . "\n"; 33 echo " 値: " . ($entity->nodeValue ?: 'なし') . "\n"; 34 echo " 公開ID: " . ($entity->publicId ?: 'なし') . "\n"; 35 echo " システムID: " . ($entity->systemId ?: 'なし') . "\n"; 36 echo "----\n"; 37 } 38 } 39 } else { 40 echo " このドキュメントタイプにはエンティティが定義されていません。\n"; 41 } 42 } else { 43 echo "ドキュメントタイプ (DOCTYPE) が見つからないか、有効なDOMDocumentTypeではありません。\n"; 44 } 45} 46 47// サンプル1: 内部サブセットDTDでカスタムエンティティを定義したコンテンツ 48$sampleContentWithInternalDtd = <<<HTML 49<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [ 50 <!ENTITY myCopyright "My Company © 2023"> 51 <!ENTITY myProduct "SuperApp™"> 52]> 53<html> 54<head><title>DTDエンティティテスト</title></head> 55<body> 56 <p>著作権情報: &myCopyright;</p> 57 <p>製品名: &myProduct;.</p> 58</body> 59</html> 60HTML; 61 62echo "--- サンプル1: 内部DTDサブセットを持つドキュメント ---\n"; 63displayDocumentTypeEntities($sampleContentWithInternalDtd); 64echo "\n"; 65 66// サンプル2: 典型的なHTML5ドキュメント (通常、DTDにカスタムエンティティは定義されません) 67$sampleHtml5Content = <<<HTML 68<!DOCTYPE html> 69<html> 70<head><title>HTML5テスト</title></head> 71<body> 72 <p>これは一般的なHTML5ドキュメントです。</p> 73 <p>例: & < ></p> 74</body> 75</html> 76HTML; 77 78echo "--- サンプル2: 標準的なHTML5ドキュメント ---\n"; 79displayDocumentTypeEntities($sampleHtml5Content); 80
PHPのDOMDocumentType::entitiesプロパティは、HTMLやXMLドキュメントのDTD(Document Type Definition)に定義されているエンティティの情報を取得するために使用されます。このプロパティは、テキスト内の&のようなHTML特殊文字エンティティをデコードする一般的な処理とは異なるためご注意ください。entitiesプロパティには引数はなく、戻り値としてDOMNamedNodeMapオブジェクトを返します。このマップには、DTDで定義された個々のエンティティがDOMEntityオブジェクトとして含まれており、それぞれのエンティティの名前、値、公開ID、システムIDといった詳細な情報にアクセスできます。
提供されたサンプルコードでは、まず与えられたHTMLまたはXML文字列をDOMDocumentオブジェクトとして読み込み、そのドキュメントタイプ(DOCTYPE)情報を取得しています。次に、取得したDOMDocumentTypeオブジェクトのentitiesプロパティを利用して、DTDに定義されたエンティティのコレクションを取得しています。このコレクションをループ処理することで、DTDにカスタムエンティティが定義されている場合に、その名前や詳細な情報を画面に出力します。これにより、ドキュメントの構造内で宣言されたエンティティの定義内容をプログラムから確認することが可能になります。例えば、内部DTDサブセットで定義された著作権情報や製品名のエンティティがどのように取得されるかを確認できます。
このコードは、HTMLやXMLドキュメントの「DTD(Document Type Definition)」に明示的に定義された「カスタムエンティティ」(例: <!ENTITY myEntity "value">)の情報を取得するものです。初心者の方がよく行う「&」のようなHTML特殊文字エンティティをテキストからデコード・除去する処理とは異なるため、混同しないように注意してください。一般的なHTML特殊文字の処理にはhtmlspecialchars_decode()などの関数を利用します。現代のウェブ開発、特にHTML5ドキュメントでは、DTD内にカスタムエンティティを定義することは稀なため、このプロパティはほとんどの場合で空のリストを返します。したがって、特定のDTDに依存する古いXML文書などを扱う場合を除き、利用機会は少ないでしょう。また、@でエラーを抑制する際は、ドキュメントのパースエラーを見逃さないよう慎重に扱う必要があります。