【PHP8.x】Dom\ProcessingInstruction::C14N()メソッドの使い方
C14Nメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『C14Nメソッドは、処理命令ノード(ProcessingInstruction)をW3Cが定めるXML正規化(Canonicalization)の仕様に従って文字列に変換する処理を実行するメソッドです。XMLの正規化とは、XML文書の論理的な意味を保ったまま、その物理的な表現を標準的で一意な形式に変換するプロセスを指します。例えば、属性の記述順序や空白文字の扱いなどを統一されたルールに基づいて整形することで、見た目や保存形式が異なっていても論理的に等価なXML文書であれば、まったく同じ文字列を生成できます。この特性は、XML文書のデジタル署名において、データが改ざんされていないかを正確に検証する際などに非常に重要となります。このメソッドでは、排他的正規化を行うか、コメントを含めるか、といった挙動を引数で細かく制御することが可能です。処理が成功すると正規化されたノードを表す文字列を返し、失敗した場合にはfalseを返します。
構文(syntax)
1public Dom\ProcessingInstruction::C14N( 2 ?string $xpath = null, 3 bool $exclusive = false, 4 bool $withComments = false, 5 ?array $nsPrefixes = null 6): string|false
引数(parameters)
bool $exclusive = false, bool $withComments = false, ?array $xpath = null, ?array $nsPrefixes = null
- bool $exclusive = false: 排他Canonicalizationを実行するかどうかを指定します。
trueの場合、指定されたXPath式に一致しない要素は無視されます。 - bool $withComments = false: C14N処理にコメントを含めるかどうかを指定します。
- ?array $xpath = null: Canonicalizationの対象となる要素を制限するためのXPath式の配列を指定します。
- ?array $nsPrefixes = null: NamespaceのプリフィックスをCanonicalizationに含めるかどうかを制御するための配列を指定します。
戻り値(return)
string|false
このメソッドは、DOMノードのCANONICAL XML形式での文字列表現を返します。指定されたノードとその子孫がCANONICAL XML仕様に準拠している場合にのみ、文字列として返され、そうでない場合はfalseが返されます。
サンプルコード
PHP 8 Dom::ProcessingInstruction::C14N()でXML処理命令を正規化する
1<?php 2 3/** 4 * Dom\ProcessingInstruction::C14N() の使用例を示します。 5 * 6 * XMLドキュメント内の処理命令ノード(例: <?xml-stylesheet ...?>)を 7 * 正規化(Canonicalize)し、その結果を文字列として出力します。 8 */ 9function demonstrateXmlProcessingInstructionC14N(): void 10{ 11 // 1. 処理命令を含むXML文字列を準備します。 12 // <?xml-stylesheet ...?> が処理命令ノード (Processing Instruction) です。 13 $xmlString = <<<XML 14<?xml version="1.0" encoding="UTF-8"?> 15<?xml-stylesheet type="text/css" href="style.css"?> 16<root> 17 <element>Hello, World!</element> 18</root> 19XML; 20 21 // 2. DOMDocumentオブジェクトを作成し、XMLを読み込みます。 22 $doc = new DOMDocument(); 23 $doc->loadXML($xmlString); 24 25 // 3. 処理命令ノードを取得します。 26 // ドキュメント直下の子ノードを調べ、最初の処理命令ノードを探します。 27 $piNode = null; 28 foreach ($doc->childNodes as $node) { 29 // ノードが Dom\ProcessingInstruction のインスタンスかチェックします。 30 if ($node instanceof Dom\ProcessingInstruction) { 31 $piNode = $node; 32 break; 33 } 34 } 35 36 // 4. 処理命令ノードが見つかった場合に正規化を実行します。 37 if ($piNode) { 38 // C14N()メソッドは、ノードを「正規化」した文字列を返します。 39 // 正規化とは、論理的に等価なXML表現が、物理的(バイト単位)にも 40 // 同一の表現になるように変換する標準的なプロセスです。 41 // XML署名などでデータの完全性を検証する際に重要となります。 42 $canonicalizedOutput = $piNode->C14N(); 43 44 if ($canonicalizedOutput !== false) { 45 echo "正規化された処理命令ノード:" . PHP_EOL; 46 // 出力結果: <?xml-stylesheet href="style.css" type="text/css"?> 47 // (属性の順序がアルファベット順に変わることに注意してください) 48 echo $canonicalizedOutput . PHP_EOL; 49 } else { 50 echo "正規化に失敗しました。" . PHP_EOL; 51 } 52 } else { 53 echo "処理命令ノードが見つかりませんでした。" . PHP_EOL; 54 } 55} 56 57// 関数を呼び出してサンプルを実行します。 58demonstrateXmlProcessingInstructionC14N();
Dom\ProcessingInstruction::C14N()メソッドは、XMLドキュメント内の処理命令ノード(例: <?xml-stylesheet ...?>)を、W3Cが定める正規化(Canonicalization)のルールに従って整形し、その結果を文字列として取得するためのものです。正規化とは、論理的に同じ意味を持つXMLデータを、物理的(バイト単位)に完全に同一の表現に変換する標準的なプロセスのことです。これは、XML署名などでデータの完全性を検証する際に非常に重要となります。
サンプルコードでは、まずXML文字列をDOMDocumentオブジェクトとして読み込み、その中から<?xml-stylesheet ...?>で表される処理命令ノードを取得しています。次に、そのノードオブジェクトに対してC14N()メソッドを呼び出します。このメソッドが実行されると、ノードは正規化ルールに基づいて整形されます。コードの実行結果を見ると、元のXMLではtype属性が先でしたが、正規化後は属性名がアルファベット順に並び替えられhrefが先になっていることが確認できます。
このメソッドには、正規化の挙動を細かく制御するための引数がありますが、省略した場合は標準のルールが適用されます。戻り値は、処理が成功した場合は正規化された文字列を、失敗した場合はfalseを返します。
このコードで使われている C14N() メソッドは、XML署名などでデータの同一性を厳密に比較するために、XMLを標準的な形式へ変換する処理です。このメソッドは処理に失敗すると false を返すため、サンプルコードのように !== false を使った厳密な比較で、必ず戻り値を検証してください。正規化された結果は、属性がアルファベット順に並び替えられるなど、元の文字列と完全には一致しない点に注意が必要です。これは仕様通りの正しい動作です。また、このコードは特定の処理命令ノードのみを対象としており、XML文書全体を正規化する DOMDocument::C14N() とは役割が異なります。