【PHP8.x】DOMProcessingInstruction::C14NFile()メソッドの使い方
C14NFileメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『C14NFileメソッドは、DOMProcessingInstructionオブジェクトが表すXML処理命令ノードをW3Cの仕様に準拠した正規形(Canonical Form)に変換し、その結果を指定されたファイルに保存する処理を実行するメソッドです。XMLの正規化とは、意味的な内容を変えることなく、XML文書を一貫性のあるバイト表現に変換するプロセスを指します。これにより、例えばデジタル署名の検証のように、異なる環境で生成されたXML文書であってもバイトレベルでの厳密な比較が可能になります。このメソッドは、同じクラスに属するC14Nメソッドと似ていますが、C14Nメソッドが正規化された結果を文字列として返すのに対し、C14NFileメソッドは直接ファイルへ出力する点が異なります。第一引数で出力先のファイルURIを指定し、オプションの引数を利用して、コメントノードを含めるか、排他的正規化を適用するかといった詳細な制御も可能です。処理に成功した場合は書き込まれたバイト数を、失敗した場合はfalseを返します。
構文(syntax)
1<?php 2// DOMDocumentと処理命令(Processing Instruction)ノードを準備します 3$doc = new DOMDocument(); 4$doc->loadXML('<?xml version="1.0"?><?target data?><root/>'); 5$piNode = $doc->childNodes[1]; // <?target data?> を取得 6 7// 出力先のファイルパス 8$filePath = 'canonicalized_pi.xml'; 9 10// 処理命令ノードを正規化(C14N)し、指定したファイルに保存します 11$bytesWritten = $piNode->C14NFile($filePath); 12?>
引数(parameters)
string $uri, bool $exclusive = false, bool $withComments = false, ?array $xpath = null, ?array $nsPrefixes = null
- string $uri: 正規化するXML文書のURIを指定します。
- bool $exclusive = false: 排他的正規化を行うかどうかを指定します。trueの場合、指定されたXPath式に一致するノードのみが正規化されます。
- bool $withComments = false: コメントを含めて正規化するかどうかを指定します。trueの場合、コメントも正規化対象となります。
- ?array $xpath = null: 排他的正規化を行う場合に、正規化対象とするノードを指定するためのXPath式を格納した配列です。
- ?array $nsPrefixes = null: 名前空間のプレフィックスを正規化対象として指定するための配列です。
戻り値(return)
int|false
C14NFileメソッドは、DOMツリーの正規化処理が成功した場合は整数(1)を返します。処理が失敗した場合はfalseを返します。
サンプルコード
PHP: Processing Instruction の C14NFile を実行する
1<?php 2 3/** 4 * DOMProcessingInstruction::C14NFile メソッドの使用例。 5 * 6 * このメソッドは実際には DOMNode::C14NFile であり、 7 * DOMProcessingInstruction は DOMNode を継承しているため、そのインスタンスから呼び出し可能です。 8 * 指定された Processing Instruction ノードの正規化されたXML表現をファイルに書き出します。 9 * 10 * @return void 11 */ 12function demonstrateC14NFileForProcessingInstruction(): void 13{ 14 // 1. DOMDocument オブジェクトを作成します。 15 // XML 1.0, UTF-8 エンコーディングを指定します。 16 $dom = new DOMDocument('1.0', 'UTF-8'); 17 18 // 2. Processing Instruction (PI) ノードを作成します。 19 // ここでは、一般的な XML スタイルシートの PI を例とします。 20 // ターゲットは 'xml-stylesheet'、データは 'type="text/xsl" href="style.xsl"' です。 21 $processingInstruction = $dom->createProcessingInstruction( 22 'xml-stylesheet', 23 'type="text/xsl" href="style.xsl"' 24 ); 25 26 // 3. 作成した PI ノードを DOM ドキュメントに追加します。 27 // PI は通常、XML ドキュメントの先頭、またはルート要素の前に配置されます。 28 $dom->appendChild($processingInstruction); 29 30 // 4. (オプション) より完全な XML ドキュメントを想定し、ルート要素とテキストノードを追加します。 31 // これらの要素は、C14NFile が $processingInstruction に適用される際には出力されません。 32 $rootElement = $dom->createElement('document'); 33 $dom->appendChild($rootElement); 34 $textNode = $dom->createTextNode('This is some sample content.'); 35 $rootElement->appendChild($textNode); 36 37 // 5. 正規化された出力を保存するファイルパスを指定します。 38 // __DIR__ は現在のスクリプトのディレクトリを表します。 39 $outputFilePath = __DIR__ . '/canonical_pi_output.xml'; 40 41 echo "正規化された Processing Instruction をファイルに書き込みます。\n"; 42 echo "出力ファイル: " . $outputFilePath . "\n\n"; 43 44 // 6. DOMProcessingInstruction インスタンス ($processingInstruction) から 45 // C14NFile メソッドを呼び出します。 46 // これは DOMNode::C14NFile を呼び出すことに相当します。 47 // 引数: 48 // $outputFilePath: 出力先のファイルパス 49 // false: 排他的正規化モードではない (デフォルト) 50 // false: コメントを含めない (デフォルト。Processing Instruction ノード自体はコメントを持ちません) 51 // null: XPath フィルタリングなし (デフォルト) 52 // null: 名前空間プレフィックスフィルタリングなし (デフォルト) 53 $bytesWritten = $processingInstruction->C14NFile($outputFilePath, false, false, null, null); 54 55 // 7. 結果をチェックし、ユーザーに通知します。 56 if ($bytesWritten === false) { 57 echo "エラー: C14NFile の実行に失敗しました。\n"; 58 } else { 59 echo $bytesWritten . " バイトが " . $outputFilePath . " に正常に書き込まれました。\n"; 60 echo "生成されたファイルの内容は以下のとおりです:\n"; 61 // ファイルの内容を読み込んで表示します。 62 echo "----------------------------------------\n"; 63 echo file_get_contents($outputFilePath); 64 echo "\n----------------------------------------\n"; 65 } 66 67 // (オプション) サンプルコード実行後に生成されたファイルを削除するには、以下のコメントを解除してください。 68 // if (file_exists($outputFilePath)) { 69 // unlink($outputFilePath); 70 // echo "\n一時ファイル " . $outputFilePath . " を削除しました。\n"; 71 // } 72} 73 74// 関数を実行してデモンストレーションを開始します。 75demonstrateC14NFileForProcessingInstruction();
PHPのDOMProcessingInstruction::C14NFileメソッドは、XML文書内の特定のProcessing Instruction(処理命令)ノードをXML正規化(Canonical XML、略してC14N)の規則に従ってファイルに書き出すための機能です。このメソッドは、DOMProcessingInstructionクラスがDOMNodeクラスを継承しているため、実質的にはDOMNode::C14NFileとして機能します。XML正規化は、XML文書の異なる物理表現(例えば、空白の有無や属性の順序の違いなど)を統一された形式に変換し、内容的に同一であるかを確実に比較できるようにするための標準化された方法です。
このメソッドの第一引数string $uriには、正規化されたXMLを出力するファイルのパスを指定します。続く引数bool $exclusiveは排他的正規化モード(デフォルトはfalseで非排他的)を使うかを、bool $withCommentsはコメントを含めるか(デフォルトはfalse)を指定します。Processing Instructionノード自体はコメントを持ちませんが、DOMNodeの機能としてこのオプションが存在します。また、?array $xpathで特定のノードをXPathで絞り込んだり、?array $nsPrefixesで名前空間プレフィックスを限定したりすることもできます。
処理が成功すると、ファイルに書き込まれたバイト数がint型で返されます。何らかの理由で書き込みに失敗した場合はfalseが返されます。サンプルコードでは、XMLのProcessing Instructionノードを生成し、その正規化された表現が指定されたファイルに正確に書き出される様子を示しています。
このコードは、XMLの特定のノードを正規化しファイルに書き出すDOMNode::C14NFileメソッドの利用例です。DOMProcessingInstructionクラスから呼び出していますが、これはDOMNodeを継承しているため可能です。出力先ファイルパスには、書き込み権限のある場所を指定してください。処理が失敗すると戻り値がfalseとなるため、必ずエラーチェックを行ってください。このメソッドは、呼び出したノード自身のみを正規化の対象とし、その子ノードなどは含みません。また、排他的正規化やコメントの有無、XPathによる対象ノードの絞り込みなど、引数で細かく挙動を制御できることを覚えておくと良いでしょう。
PHP XML C14NFile で正規化して保存
1<?php 2 3/** 4 * XMLドキュメントを正規化し、その結果を指定されたファイルに書き込みます。 5 * 6 * この関数は、XMLドキュメントの内容をXML正規化アルゴリズム(C14N)に従って処理し、 7 * 結果を新しいファイルとして保存する方法を示します。 8 * ファイルの内容を「コピー」または「保存」するような操作であるため、 9 * キーワード 'cp' (copy) に関連付けて理解できます。 10 * 11 * 注: 提供されたリファレンス情報では「DOMProcessingInstruction」クラスにC14NFileメソッドが 12 * あるとされていますが、標準のPHP DOM拡張では「DOMDocument」または「DOMNode」クラスに 13 * C14NFileメソッドが存在します。このサンプルコードでは、一般的にXMLドキュメント全体を 14 * 正規化するために使われる「DOMDocument::C14NFile」メソッドを使用しています。 15 * 16 * @param string $inputXmlFilePath 入力となるXMLファイルのパス。 17 * @param string $outputFilePath 正規化されたXMLを書き出すファイルのパス。 18 * @param bool $exclusive 排他的な正規化を使用するかどうか。 19 * @param bool $withComments コメントを正規化に含めるかどうか。 20 * @return bool 成功した場合はtrue、失敗した場合はfalse。 21 */ 22function canonicalizeXmlToFile( 23 string $inputXmlFilePath, 24 string $outputFilePath, 25 bool $exclusive = false, 26 bool $withComments = false 27): bool { 28 // 1. DOMDocumentインスタンスを作成 29 $dom = new DOMDocument('1.0', 'UTF-8'); 30 // XMLドキュメントの空白を保持せず、整形して出力するように設定 31 // (正規化の結果には直接影響しませんが、デバッグ時の視認性を高めます) 32 $dom->preserveWhiteSpace = false; 33 $dom->formatOutput = true; 34 35 // 2. 指定されたXMLファイルを読み込む 36 if (!file_exists($inputXmlFilePath)) { 37 echo "エラー: 入力ファイル '{$inputXmlFilePath}' が見つかりません。\n"; 38 return false; 39 } 40 if (!$dom->load($inputXmlFilePath)) { 41 echo "エラー: XMLファイル '{$inputXmlFilePath}' の読み込みに失敗しました。\n"; 42 return false; 43 } 44 45 echo "XMLドキュメントを正規化し、ファイル '{$outputFilePath}' に書き込みます。\n"; 46 47 // 3. C14NFileメソッドを呼び出して、正規化されたXMLをファイルに書き込む 48 // このメソッドは、XMLドキュメントの正規化された形式を指定されたURI(ファイルパス)に書き出します。 49 // 戻り値: 書き込まれたバイト数 (int) または失敗時に false 50 $bytesWritten = $dom->C14NFile( 51 $outputFilePath, 52 $exclusive, 53 $withComments 54 // XPathフィルタリングや名前空間プレフィックスの指定は、今回は省略 55 ); 56 57 if ($bytesWritten === false) { 58 echo "エラー: XMLの正規化とファイルへの書き込みに失敗しました。\n"; 59 return false; 60 } else { 61 echo "成功: '{$outputFilePath}' に {$bytesWritten} バイトを書き込みました。\n"; 62 // 書き出されたファイルの内容を確認 63 echo "--- '{$outputFilePath}' の内容 ---\n"; 64 echo file_get_contents($outputFilePath) . "\n"; 65 echo "---------------------------\n"; 66 return true; 67 } 68} 69 70// --- サンプルコードの実行部分 --- 71 72// 1. サンプル入力XMLコンテンツの作成 73$sampleInputXml = <<<XML 74<?xml version="1.0" encoding="UTF-8"?> 75<!-- これはテストコメントです --> 76<root attr="value"> 77 <child> 78 Hello World! 79 </child> 80 <?php echo 'Processing Instruction'; ?> 81</root> 82XML; 83 84$inputFileName = 'input_sample.xml'; 85$outputFileName = 'output_canonicalized.xml'; 86 87// 2. サンプル入力XMLファイルをディスクに保存 88file_put_contents($inputFileName, $sampleInputXml); 89echo "サンプル入力ファイル '{$inputFileName}' を作成しました。\n"; 90 91// 3. `canonicalizeXmlToFile` 関数を実行 92// 排他的正規化は false、コメントを含めるは true で実行 93canonicalizeXmlToFile($inputFileName, $outputFileName, false, true); 94 95// 4. 使用したファイルをクリーンアップ(削除) 96if (file_exists($inputFileName)) { 97 unlink($inputFileName); 98 echo "サンプル入力ファイル '{$inputFileName}' を削除しました。\n"; 99} 100if (file_exists($outputFileName)) { 101 unlink($outputFileName); 102 echo "出力ファイル '{$outputFileName}' を削除しました。\n"; 103}
DOMDocument::C14NFileメソッドは、XMLドキュメントの内容を特定のルール(XML正規化アルゴリズム、C14N)に従って処理し、その結果を新しいファイルとして保存する際に使用します。これは、既存のXMLファイルを正規化して別のファイルに「コピー」または「保存」するような操作であるため、cp(copy)というキーワードに関連付けて理解できます。
このサンプルコードでは、DOMDocumentクラスのインスタンスを作成し、loadメソッドでXMLファイルを読み込んでいます。読み込んだXMLドキュメントに対し、C14NFileメソッドを呼び出すことで、正規化されたXMLデータが指定されたファイルパス($uri引数)に書き出されます。
$exclusive引数は排他的な正規化を行うかどうかを、$withComments引数はコメントを正規化結果に含めるかどうかを真偽値で指定します。メソッドが成功すると書き込まれたバイト数(int)が返され、ファイルへの書き込みに失敗した場合はfalseが返されます。
提供されたリファレンス情報ではDOMProcessingInstructionクラスにこのメソッドがあるとされていますが、一般的にXMLドキュメント全体を正規化するために使用されるのはDOMDocumentクラスのC14NFileメソッドであり、このサンプルコードもそのように実装されています。
リファレンスのDOMProcessingInstructionではなく、DOMDocumentクラスにC14NFileメソッドが存在します。このメソッドは、XMLドキュメントの内容をXML正規化アルゴリズムに従って処理し、その結果を指定されたファイルに書き出す機能です。単なるファイルコピー(cp)とは異なり、XMLの構造を標準化するため、元のファイルと異なる内容が書き出される場合がありますのでご注意ください。成功時には書き込まれたバイト数、失敗時にはfalseが返されるため、必ず戻り値を確認し、エラー処理を適切に行ってください。引数で排他的正規化やコメントの有無を指定すると、正規化結果に影響しますので、目的に応じて設定してください。入力ファイルの存在確認やXML読み込みのエラー処理も重要です。