【PHP8.x】entitiesプロパティの使い方
entitiesプロパティの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
entitiesプロパティは、Dom\DocumentTypeクラスに属し、ドキュメント型定義(DTD)内で宣言されている一般エンティティの定義情報を保持するプロパティです。
Dom\DocumentTypeクラスは、HTMLやXMLドキュメントのDOCTYPE宣言、つまりドキュメントの構造や使用できる要素、属性、そしてエンティティなどのルールを定義した部分を表します。エンティティとは、例えば著作権記号のような特殊文字や、繰り返し使用される長い文字列などを短い名前で参照できるようにする仕組みのことです。
このentitiesプロパティは、DOCTYPE宣言内で定義されているこれらのエンティティのリストをDom\NamedNodeMapオブジェクトとして提供します。Dom\NamedNodeMapは、名前でアクセスできるノードの集合を扱うためのインターフェースです。個々のエンティティ定義は、その名前を使ってこのMapから取得することができます。
重要な点として、このプロパティはドキュメント内で実際に参照されたエンティティ(例えば「©」)が展開された結果ではなく、あくまでDTD自体に記述された「エンティティの定義情報」そのものの集合を保持しています。そのため、このプロパティは、DOM拡張機能を利用してドキュメントのDTDをプログラムで解析し、どのようなエンティティが定義されているかを確認したり、ドキュメントの構造を深く理解したりする際に役立ちます。システムエンジニアにとって、XMLやHTMLのスキーマを理解し、バリデーションや変換処理を行う上で、このようなDTDのメタデータにアクセスできることは非常に重要です。
構文(syntax)
1<?php 2 3$xml = <<<XML 4<?xml version="1.0" encoding="UTF-8"?> 5<!DOCTYPE root [ 6 <!ENTITY company "Example Corp."> 7 <!ENTITY year "2023"> 8]> 9<root> 10 <item>Document by &company; in &year;.</item> 11</root> 12XML; 13 14$dom = new DOMDocument(); 15$dom->loadXML($xml); 16 17$doctype = $dom->doctype; 18 19if ($doctype instanceof DOMDocumentType) { 20 $entities = $doctype->entities; 21 22 if ($entities) { 23 foreach ($entities as $entity) { 24 echo "Entity Name: " . $entity->nodeName . ", Value: " . $entity->nodeValue . "\n"; 25 } 26 } 27} 28 29?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
DOMNamedNodeMap
Dom\DocumentType クラスの entities プロパティは、その文書型宣言で宣言されているエンティティのコレクションを表す DOMNamedNodeMap オブジェクトを返します。このマップには、エンティティ名がキーとして、各エンティティを表す DOMEntity オブジェクトが値として格納されています。
サンプルコード
PHPでXML DTDエンティティを取得する
1<?php 2 3/** 4 * XMLドキュメントからDTDエンティティの定義を取得し、その情報を表示します。 5 * 6 * この関数は、XMLのDTD(Document Type Definition)で定義されたカスタムエンティティが、 7 * ドキュメント内でどのように「符号化」または「表現」されるか(エンティティ名とその実体値)を示します。 8 * 「php entities encode」というキーワードに関連して、エンティティの定義内容が 9 * 実際にXML内で何に「エンコード」(置き換え)されるかを示しています。 10 * システムエンジニアを目指す初心者の方でも、DTDエンティティの概念と、 11 * それをPHPでプログラムからどう扱うかを理解しやすいように設計されています。 12 * 13 * @param string $xmlString DTDを含むXML文字列。 14 * @return void 15 */ 16function displayXmlEntities(string $xmlString): void 17{ 18 // DOMDocumentオブジェクトを作成します。 19 // これはXMLパーサーとして機能し、XMLドキュメントの構造を操作するための基盤となります。 20 $dom = new Dom\DOMDocument(); 21 // 厳密なエラーチェックを有効にし、XMLの構文解析時に問題があれば通知するようにします。 22 $dom->validateOnParse = true; 23 24 // 提供されたXML文字列をDOMDocumentにロードします。 25 // loadXML()メソッドは、文字列からXMLドキュメントを解析します。 26 // このプロセスで、XML内に定義されたDTDエンティティも読み込まれます。 27 $dom->loadXML($xmlString); 28 29 // ドキュメントタイプノードを取得します。 30 // XMLドキュメントのDTD情報(エンティティ定義など)がこのオブジェクトに含まれています。 31 $documentType = $dom->doctype; 32 33 // ドキュメントタイプノードが存在する場合のみ処理を進めます。 34 // DTDが定義されていないXMLやHTMLドキュメントでは、$documentType は null になります。 35 if ($documentType instanceof Dom\DocumentType) { 36 echo "--- DTDエンティティのリスト ---\n"; 37 38 // Dom\DocumentType::entities プロパティは、DTDで定義されたエンティティの 39 // DOMNamedNodeMap(名前でアクセス可能なノードのコレクション)を返します。 40 // ここには、各エンティティがどのような値に「エンコード」(置き換え)されるかの 41 // 定義がコレクションとして含まれています。 42 $entities = $documentType->entities; 43 44 // エンティティが1つ以上定義されているか確認します。 45 if ($entities->length > 0) { 46 // 各エンティティノードをループして情報を表示します。 47 foreach ($entities as $entity) { 48 /** @var Dom\DOMEntity $entity */ // 型ヒント:$entityがDom\DOMEntityであることを示します 49 echo " エンティティ名: " . $entity->nodeName . "\n"; 50 // nodeValue は、そのエンティティがXMLドキュメント内で参照された場合に、 51 // 実際に展開される文字列(「実体値」)を示します。 52 // これは、エンティティが何に「エンコード」されているかを示していると言えます。 53 echo " 実体値 (エンコードされた内容): " . $entity->nodeValue . "\n"; 54 echo "\n"; 55 } 56 } else { 57 echo " このドキュメントタイプにはエンティティ定義が見つかりませんでした。\n"; 58 } 59 } else { 60 echo "ドキュメントタイプノードが見つかりませんでした。\n"; 61 echo "XMLにDTD(Document Type Definition)が定義されていない可能性があります。\n"; 62 } 63} 64 65// -------------------------------------------------------------------------- 66// サンプルコードの実行例 67// -------------------------------------------------------------------------- 68 69// DTD内部サブセットでカスタムエンティティを定義したXML文字列の例。 70// <!DOCTYPE document [...]> の部分で 'greeting', 'company', 'copyright' という 71// 3つのエンティティが定義されています。 72$sampleXmlWithEntities = <<<XML 73<!DOCTYPE document [ 74 <!ENTITY greeting "Hello, World!"> 75 <!ENTITY company "Example Corp."> 76 <!ENTITY copyright "Copyright © 2023."> 77]> 78<document> 79 <message>&greeting;</message> 80 <info>Manufactured by &company;.</info> 81 <footer>©right;</footer> 82</document> 83XML; 84 85// 上記のXML文字列を解析し、DTDエンティティの情報を表示します。 86displayXmlEntities($sampleXmlWithEntities); 87 88?>
このPHPサンプルコードは、XMLドキュメント内に定義されたDTD(Document Type Definition)エンティティの情報を取得し、表示する方法を示しています。エンティティとは、XML内で特定の名前を定義し、それを別の文字列(実体値)に「エンコード」(置き換え)する仕組みです。これにより、共通のテキストや特殊文字を簡潔に表現できます。
コードの中心となるのは、Dom\DocumentTypeクラスのentitiesプロパティです。このプロパティは、DTDで定義されたすべてのエンティティのコレクションをDOMNamedNodeMapとして返します。このコレクションに含まれる各エンティティは、エンティティ名(nodeName)と、それが実際にXML内で何に「エンコード」(置き換え)されるかを示す実体値(nodeValue)を持っています。
displayXmlEntities関数は、DTDを含むXML文字列を引数($xmlString)として受け取ります。関数内部では、まずDom\DOMDocumentオブジェクトにXMLをロードし、$dom->doctypeプロパティでドキュメントタイプ情報を取得します。次に、$documentType->entitiesプロパティを用いてエンティティのコレクションを取得し、その中をループして各エンティティの名前と実体値を画面に出力します。この関数自体は情報を表示するのみで、特定の値を返しません(void)。Dom\DocumentType::entitiesプロパティは引数を取らず、DOMNamedNodeMapを戻り値として返します。これにより、プログラムからXMLのDTDエンティティ定義を正確に把握し、利用することが可能となります。
Dom\DocumentType::entitiesプロパティを利用するには、解析対象のXMLにDTD(Document Type Definition)が明確に定義されている必要があります。DTDが存在しないXMLでは、$dom->doctypeがnullとなるため、必ずプロパティにアクセスする前にnullチェックまたはinstanceofで型の確認を行ってください。このプロパティは、DTD内で定義されたエンティティのコレクションであるDOMNamedNodeMapを返します。ここから各エンティティのnodeName(エンティティ名)とnodeValue(実体値)を取得することで、エンティティがXML内で何に「エンコード」(置き換え)されるかを確認できます。外部から提供されるXMLを解析する際には、XML外部エンティティ(XEE)攻撃などのセキュリティリスクを考慮し、libxml_disable_entity_loader(true)のような対策を検討することが重要です。このプロパティはDTDエンティティの定義取得に特化しており、HTMLの特殊文字参照とは扱いが異なります。