【PHP8.x】Dom\ProcessingInstruction::C14NFile()メソッドの使い方
C14NFileメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
C14NFileメソッドは、処理命令ノードをW3Cの勧告に従って正規化(Canonicalization, C14N)し、その結果を指定されたファイルに出力するメソッドです。正規化とは、XML文書の論理的に等価な表現を、物理的に一意なバイト表現に変換するプロセスのことです。例えば、属性の記述順序や空白文字の有無が異なる二つのXML文書でも、内容が同じであれば正規化後には全く同一のデータとなります。この特性は、XMLデジタル署名などでデータの完全性を検証する際に非常に重要です。このメソッドは、呼び出し元のDom\ProcessingInstructionオブジェクトを正規化の対象とし、第一引数で指定されたファイルパスにその結果を書き込みます。また、排他的正規化の有効化、コメントノードの包含有無、特定の名前空間の扱いなど、複数のオプションパラメータによって正規化の挙動を細かく制御することが可能です。処理が成功した場合はファイルに書き込まれたバイト数を、失敗した場合はfalseを返します。
構文(syntax)
1<?php 2$document = new DOMDocument(); 3 4// Dom\ProcessingInstruction オブジェクトを生成します 5$pi = $document->createProcessingInstruction( 6 'xml-stylesheet', 7 'type="text/xsl" href="style.xsl"' 8); 9 10// オブジェクトの C14NFile() メソッドを呼び出し、 11// 正規化されたノードをファイルに出力します。 12$pi->C14NFile( 13 'path/to/output.xml', // uri 14 false, // exclusive 15 false, // withComments 16 null, // xpath 17 false // nsPrefixes 18);
引数(parameters)
string $uri, bool $exclusive = false, bool $withComments = false, ?array $xpath = null, ?array $nsPrefixes = null
- string $uri: 正規化するXMLファイルへのURIを指定します。
- bool $exclusive = false: 排他ノードセットを行使するかどうかを指定します。
- bool $withComments = false: コメントを含めて正規化するかどうかを指定します。
- ?array $xpath = null: 正規化の対象となるノードをXPathで指定します。
- ?array $nsPrefixes = null: 名前空間のプレフィックスをマッピングする連想配列を指定します。
戻り値(return)
int|false
C14NFileメソッドは、DOM構造をC14N形式でシリアライズする際のバイト数を返します。処理が成功した場合はそのバイト数(整数)を返し、失敗した場合はfalseを返します。
サンプルコード
PHP C14NFileで処理命令を正規化する
1<?php 2 3/** 4 * Dom\ProcessingInstruction オブジェクトを含む Dom\Document に対して C14NFile メソッドを使用するサンプルコード。 5 * 6 * 注意: PHP標準のDom\ProcessingInstructionクラスにはC14NFileメソッドは直接存在しません。 7 * C14NFileメソッドは通常、Dom\Document または Dom\Node (Dom\Elementなど) のインスタンスに対して利用されます。 8 * このサンプルコードでは、処理命令を含むXMLドキュメント全体を正規化することで、 9 * 提供されたリファレンス情報の意図を汲み取り、関連性を示します。 10 */ 11function demonstrateProcessingInstructionC14NFile(): void 12{ 13 // XML ドキュメントを作成します。 14 $document = new Dom\Document('1.0', 'UTF-8'); 15 // 出力されるXMLを見やすくするためにフォーマットを有効にします。 16 $document->formatOutput = true; 17 18 // ドキュメントにルート要素を追加します。 19 $root = $document->createElement('example'); 20 $document->appendChild($root); 21 22 // 処理命令 (Processing Instruction) を作成し、ドキュメントに挿入します。 23 // Dom\ProcessingInstruction オブジェクトは Dom\Document::createProcessingInstruction() を使って作成します。 24 $processingInstruction = $document->createProcessingInstruction('php', 'echo "Hello, world!";'); 25 // 通常、処理命令はルート要素の前か、ドキュメントの最初に配置されます。 26 $document->insertBefore($processingInstruction, $root); 27 28 // ドキュメントに別の要素を追加します。 29 $element = $document->createElement('item', 'これはテストデータです。'); 30 $root->appendChild($element); 31 32 // 正規化されたXMLを書き出すファイル名です。 33 $outputUri = 'c14n_output_with_pi.xml'; 34 35 // Dom\Document::C14NFile メソッドを呼び出します。 36 // このメソッドはドキュメント全体の正規化を行い、その結果を指定されたURI(ファイル)に書き出します。 37 // 引数: 38 // $uri: 出力ファイルのパス 39 // $exclusive: 排他的正規化を行うかどうか (falseで非排他的) 40 // $withComments: コメントを含めるかどうか 41 // $xpath: 正規化対象のノードを限定するXPath式の配列 (今回はnullでドキュメント全体) 42 // $nsPrefixes: 名前空間プレフィックスの配列 (今回はnull) 43 $bytesWritten = $document->C14NFile($outputUri, false, false, null, null); 44 45 if ($bytesWritten !== false) { 46 echo "処理命令を含むドキュメントの正規化結果をファイル '{$outputUri}' に書き出しました。\n"; 47 echo "書き込みバイト数: {$bytesWritten} バイト\n"; 48 echo "\n----- ファイル内容 -----\n"; 49 echo file_get_contents($outputUri); 50 echo "\n------------------------\n"; 51 } else { 52 echo "正規化結果のファイルへの書き出しに失敗しました。\n"; 53 // ファイル書き込み権限の問題などが考えられます。 54 } 55 56 // 必要であれば、生成されたファイルを削除するコードをここに記述できます。 57 // if (file_exists($outputUri)) { 58 // unlink($outputUri); 59 // } 60} 61 62// 関数を実行します。 63demonstrateProcessingInstructionC14NFile();
PHPのDOM拡張機能は、XMLドキュメントの操作と処理を行うための重要なツールです。C14NFileメソッドは、XMLドキュメントを「正規化(Canonicalization: C14N)」し、その結果を指定されたURI(通常はファイルパス)に書き出すために使用されます。正規化とは、XMLドキュメントの構造や表現を一意の形式に変換することで、例えばデジタル署名などで内容の同一性を保証する際に役立ちます。
提供されたリファレンスではDom\ProcessingInstructionクラスに属するとされていますが、実際にはこのC14NFileメソッドはDom\Documentクラスのインスタンスに対して呼び出されるのが一般的です。しかし、処理命令(Processing Instruction)もXMLドキュメントを構成するノードの一つであり、ドキュメント全体を正規化する際には、これら処理命令も正しく含まれて出力されます。
サンプルコードでは、まず新しいXMLドキュメントを作成し、Dom\Document::createProcessingInstruction()メソッドを使って処理命令を追加しています。その後、ドキュメントのルート要素も追加されます。
$document->C14NFile()メソッドは、このドキュメント全体を正規化し、結果をc14n_output_with_pi.xmlというファイルに保存します。引数$uriには出力先のファイルパス、$exclusiveは排他的正規化を行うか、$withCommentsはコメントを含めるか、$xpathと$nsPrefixesは正規化の対象を限定する場合に指定します。
このメソッドは、ファイルに書き込まれたバイト数を整数値で返すか、失敗した場合はfalseを返します。これにより、書き込みの成否を確認できます。実行すると、処理命令を含む正規化されたXMLがファイルに保存され、その内容が表示されます。
このC14NFileメソッドは、提供されたリファレンス情報ではDom\ProcessingInstructionクラスに属するとされていますが、実際にはDom\DocumentまたはDom\Nodeクラスのインスタンスに対して呼び出されるメソッドです。XMLドキュメントの内容をXML正規化し、その結果を指定されたURI(ファイルパス)に書き出す際に使用します。メソッドの呼び出し後は、ファイルへの書き込みが成功したかどうかを判断するため、戻り値がfalseでないことを必ず確認してください。指定されたファイルパスには適切な書き込み権限が必要です。このメソッドはXMLの標準的な正規化処理を実行し、異なる環境間でのXMLの比較や電子署名などに役立ちます。
PHP C14NFileでXML処理命令を正規化する
1<?php 2 3/** 4 * Dom\ProcessingInstruction::C14NFile メソッドの使用例をデモンストレーションします。 5 * 6 * この関数は、XML処理命令(Processing Instruction)を作成し、 7 * そのノードに対して C14NFile メソッドを呼び出し、 8 * 正規化された内容をファイルに書き出します。 9 * 10 * @return void 11 */ 12function demonstrateC14NFile(): void 13{ 14 // 1. 新しい DOMDocument オブジェクトを初期化します。 15 // XML バージョン1.0、エンコーディングUTF-8を指定します。 16 $dom = new DOMDocument('1.0', 'UTF-8'); 17 // 出力を整形して見やすくしますが、C14NFile の正規化結果には影響しません。 18 $dom->formatOutput = true; 19 20 // 2. ルート要素を作成し、ドキュメントに追加します。 21 // 例: <root></root> 22 $root = $dom->createElement('root'); 23 $dom->appendChild($root); 24 25 // 3. XML処理命令(Processing Instruction)を作成します。 26 // 例: <?xml-stylesheet type="text/xsl" href="style.xsl"?> 27 // リファレンス情報が Dom\ProcessingInstruction クラスを指しているため、 28 // このクラスのインスタンスに対して C14NFile を呼び出す例を示します。 29 $processingInstruction = $dom->createProcessingInstruction( 30 'xml-stylesheet', // ターゲット名(処理命令の対象) 31 'type="text/xsl" href="style.xsl"' // データ(処理命令の内容) 32 ); 33 34 // 4. 処理命令をドキュメントのルート要素の前に挿入します。 35 // 処理命令は通常、XML宣言の直後やルート要素の前に配置されます。 36 $dom->insertBefore($processingInstruction, $root); 37 38 // 5. 正規化されたXMLを保存するファイルパスを指定します。 39 $outputFile = 'normalized_processing_instruction.xml'; 40 41 // 6. Dom\ProcessingInstruction インスタンスに対して C14NFile メソッドを呼び出します。 42 // このメソッドは、この処理命令ノード自身を正規化された形式で指定されたファイルに書き出します。 43 // 引数: string $uri (出力ファイルパス), bool $exclusive (排他的正規化), bool $withComments (コメントを含めるか) 44 // 戻り値: int|false (書き込まれたバイト数、または失敗時は false) 45 $bytesWritten = $processingInstruction->C14NFile( 46 $outputFile, 47 false, // $exclusive: 排他的正規化を使用しない(通常は false) 48 false // $withComments: コメントを含めない(処理命令には通常コメントは関係しない) 49 ); 50 51 // 7. 処理結果をユーザーに通知します。 52 if ($bytesWritten === false) { 53 echo "エラー: 正規化されたXMLをファイル '{$outputFile}' に書き込めませんでした。\n"; 54 } else { 55 echo "正規化されたXMLがファイル '{$outputFile}' に書き込まれました。\n"; 56 echo "書き込まれたバイト数: {$bytesWritten} バイト。\n"; 57 echo "\nファイルの内容を確認してください。\n"; 58 59 // 作成されたファイルの内容をコンソールに表示して確認を促します。 60 if (file_exists($outputFile)) { 61 echo "\n--- '{$outputFile}' の内容 ---\n"; 62 // ファイル内容をHTMLエンティティに変換して表示し、XMLタグがブラウザで解釈されないようにします。 63 echo htmlspecialchars(file_get_contents($outputFile)); 64 echo "\n---------------------------\n"; 65 // このサンプルでは、作成したファイルは削除しません。 66 // 不要な場合は `unlink($outputFile);` で削除できます。 67 } 68 } 69} 70 71// 上記で定義した関数を実行します。 72demonstrateC14NFile();
このサンプルコードは、PHPのDom\ProcessingInstruction::C14NFileメソッドの使い方を示しています。このメソッドは、XMLの「処理命令(Processing Instruction)」ノードを、特定のルールに基づいて「正規化」し、その結果をファイルに保存するために使用されます。XMLの正規化とは、記述形式が異なっていても内容が同じXML文書は、常に同じバイト列として表現されるように統一する処理のことです。
コードではまず、新しいXMLドキュメントを作成し、<?xml-stylesheet type="text/xsl" href="style.xsl"?>のようなXML処理命令ノードを作成してドキュメントに挿入します。その後、この処理命令ノードのインスタンスに対してC14NFileメソッドを呼び出しています。
C14NFileメソッドの第一引数$uriには、正規化されたXML内容を書き出すファイルパスを指定します。第二引数$exclusiveは排他的正規化を行うかどうかを、第三引数$withCommentsはコメントを含めるかどうかをブール値で設定しますが、この例ではどちらもfalse(通常の設定)にしています。このメソッドは、ファイルに書き込まれたバイト数を整数で返しますが、書き込みに失敗した場合はfalseを返します。
最終的に、コードはファイルの書き込みが成功したかを確認し、その結果と書き込まれたバイト数を表示します。また、作成されたファイルの内容もコンソールに出力して確認を促しており、正規化された処理命令がファイルに正しく保存されたことを確認できます。
このサンプルコードは、Dom\ProcessingInstruction::C14NFileメソッドで、XML処理命令ノードを正規化しファイルに書き出す例です。
注意点は以下の通りです。このメソッドはDOMDocument全体ではなく、個別の処理命令ノードが対象です。出力ファイルパスには書き込み権限が必要です。
また、戻り値はint|falseのため、失敗時はfalseを返します。必ず=== falseで厳密にチェックし、エラーハンドリングを適切に行ってください。