【PHP8.x】DOMEntity::C14NFile()メソッドの使い方
C14NFileメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
C14NFileメソッドはDOMEntityクラスに属し、XMLドキュメント内の特定のエンティティが表す内容を、Canonical XML (C14N) 形式に正規化してファイルに出力するメソッドです。Canonical XMLとは、XMLドキュメントの内部表現に存在する可能性のある曖昧さを取り除き、その内容をバイト列として一意に表現するための標準化された方法です。例えば、属性の順序や名前空間の宣言、空白文字の扱いなど、目には見えにくい差異を統一し、どのような環境や方法で生成されたXMLであっても、その意味内容が同じであれば同じ表現となるように変換します。
このメソッドを利用することで、DOMEntityオブジェクトが保持するXMLデータを、C14N形式で永続化したり、他のシステムと確実に比較できる形式で受け渡したりすることが可能になります。特に、XMLデジタル署名の検証や、XMLドキュメントの厳密な比較を行う際に、その正確性と信頼性を保証するために非常に重要な役割を果たします。引数として出力先のファイルパスを指定し、オプションによって正規化の詳細な挙動を制御できる場合があります。処理が成功した場合には真(true)を、失敗した場合には偽(false)を返すことが期待されます。これにより、初心者の方でもXMLデータの整合性を保ちながらファイル操作を行うことができます。
構文(syntax)
1<?php 2$bytesWrittenOrFalse = $dom_entity->C14NFile( 3 'path/to/output.xml', 4 false, 5 false, 6 null, 7 null 8);
引数(parameters)
string $uri, bool $exclusive = false, bool $withComments = false, ?array $xpath = null, ?array $nsPrefixes = null
- string $uri: 正規化するXML/HTMLドキュメントのURIを指定します。
- bool $exclusive = false: trueに設定すると、排他的な正規化モードで処理します。
- bool $withComments = false: trueに設定すると、コメントノードも正規化の対象に含めます。
- ?array $xpath = null: XPath式を指定し、指定したノードのみを正規化します。
- ?array $nsPrefixes = null: 名前空間のプレフィックスを配列で指定し、正規化の対象とする名前空間を限定します。
戻り値(return)
string|bool
C14NFileメソッドは、エンティティを正規化された形式の文字列として返します。正規化に失敗した場合はfalseを返します。
サンプルコード
PHP DOMDocument C14NFile でXMLを正規化する
1<?php 2 3/** 4 * DOMDocument::C14NFile メソッドの使用例を示します。 5 * これはXMLを正規化形式(Canonical XML)でファイルに保存するメソッドです。 6 * 7 * 注: 提供されたリファレンス情報では「所属クラス: DOMEntity」とありますが、 8 * PHPの標準ライブラリにおいてC14NFileメソッドはDOMDocumentクラスに属します。 9 * ここでは、一般的な使用方法に則りDOMDocumentクラスのメソッドとして実装しています。 10 */ 11function demonstrateC14NFile(): void 12{ 13 // 一時的なXMLファイルを準備 14 $sourceXmlFile = 'temp_source.xml'; 15 $canonicalizedXmlFile = 'temp_canonicalized_output.xml'; 16 $canonicalizedXmlFileWithComments = 'temp_canonicalized_output_with_comments.xml'; 17 18 // サンプルXMLコンテンツ 19 $xmlContent = <<<XML 20<?xml version="1.0" encoding="UTF-8"?> 21<root xmlns:ex="http://example.com/ns"> 22 <!-- これはコメントです --> 23 <element attr="value"> 24 こんにちは、世界! 25 </element> 26 <ex:anotherElement/> 27</root> 28XML; 29 30 // ソースXMLファイルを一時的に作成 31 file_put_contents($sourceXmlFile, $xmlContent); 32 33 echo "--- 元のXMLファイルの内容 ---\n"; 34 echo file_get_contents($sourceXmlFile) . "\n\n"; 35 36 // DOMDocumentオブジェクトを作成し、XMLファイルをロード 37 $dom = new DOMDocument(); 38 $dom->load($sourceXmlFile); 39 40 // --- 例1: 基本的な正規化(コメントなし、非排他的) --- 41 echo "--- 例1: 基本的な正規化 (コメントなし、非排他的) ---\n"; 42 // C14NFile(string $uri, bool $exclusive = false, bool $withComments = false) 43 // $uri: 正規化されたXMLを保存するファイルパス 44 // $exclusive: 排他的な正規化を使用するか (デフォルトは false) 45 // $withComments: コメントを含めるか (デフォルトは false) 46 $result = $dom->C14NFile($canonicalizedXmlFile, false, false); 47 48 if ($result) { 49 echo "正規化されたXMLが '{$canonicalizedXmlFile}' に保存されました。\n"; 50 echo file_get_contents($canonicalizedXmlFile) . "\n\n"; 51 } else { 52 echo "基本的な正規化に失敗しました。\n\n"; 53 } 54 55 // --- 例2: コメントを含む正規化 --- 56 echo "--- 例2: コメントを含む正規化 ---\n"; 57 // withCommentsをtrueに設定して、コメントを含めて正規化 58 $resultWithComments = $dom->C14NFile($canonicalizedXmlFileWithComments, false, true); 59 60 if ($resultWithComments) { 61 echo "正規化されたXML(コメントあり)が '{$canonicalizedXmlFileWithComments}' に保存されました。\n"; 62 echo file_get_contents($canonicalizedXmlFileWithComments) . "\n\n"; 63 } else { 64 echo "コメントを含む正規化に失敗しました。\n\n"; 65 } 66 67 // --- クリーンアップ --- 68 // 作成した一時ファイルを削除 69 if (file_exists($sourceXmlFile)) { 70 unlink($sourceXmlFile); 71 } 72 if (file_exists($canonicalizedXmlFile)) { 73 unlink($canonicalizedXmlFile); 74 } 75 if (file_exists($canonicalizedXmlFileWithComments)) { 76 unlink($canonicalizedXmlFileWithComments); 77 } 78 echo "一時ファイルを削除しました。\n"; 79} 80 81// 関数を実行 82demonstrateC14NFile();
PHPのDOMDocument::C14NFileメソッドは、XML文書を「Canonical XML(正規化XML)」と呼ばれる標準的な形式で指定されたファイルに保存するための機能です。Canonical XMLとは、XMLの内容を、空白文字の扱いや属性の順序などのわずかな違いに左右されずに常に同じ形式で扱えるようにするためのルールであり、特にXMLの電子署名などで内容の同一性を保証する際に重要な役割を果たします。
このメソッドは、第一引数$uriで正規化されたXMLを保存するファイルパスを指定します。第二引数$exclusiveは排他的な正規化を行うかを真偽値で設定し、デフォルトはfalseです。第三引数$withCommentsは、元のXML内のコメントを正規化後の出力に含めるかを真偽値で指定し、デフォルトはfalseとなっています。メソッドは処理が成功した場合、正規化されたXMLの文字列を返し、失敗した場合はfalseを返します。
サンプルコードでは、まず元のXMLファイルを作成し、DOMDocumentオブジェクトに読み込んでいます。最初の例では$withCommentsをfalseに設定してコメントを含めずに正規化し、指定のファイルに保存します。次に、$withCommentsをtrueに設定してコメントも出力に含めて正規化する例を示しており、正規化の動作とファイルの出力方法を具体的に確認できます。
提供されたリファレンス情報ではDOMEntityクラスに属するとありますが、実際にはDOMDocumentクラスのメソッドとして使用しますのでご注意ください。C14NFileは、XML文書を標準的な形式に正規化し、指定されたファイルに保存するために用います。これにより、XMLの比較や署名検証などが正確に行えるようになります。引数$uriには保存先のファイルパスを必ず指定し、$exclusiveや$withCommentsで正規化の挙動を制御できます。メソッドの戻り値は、成功時には正規化されたXML文字列、失敗時にはfalseとなりますので、常に結果をチェックしてエラーハンドリングを行うことが重要です。サンプルコードのように一時ファイルを作成する際は、処理後に必ず削除し、システムのリソースを適切に管理してください。
PHP XML正規化 (C14N) でファイル保存する
1<?php 2 3/** 4 * XMLファイルをW3C勧告に基づくCanonical XML 1.0形式に正規化し、ファイルに保存します。 5 * 6 * この関数は、XMLドキュメントの内容を標準化し、異なる環境や保存方法によって生じる 7 * 些細な違い(空白、属性の順序、エンティティ参照など)をなくします。 8 * これは特にXML署名やXML暗号化など、XMLの同一性を保証する必要がある場合に重要です。 9 * 10 * @param string $inputXmlPath 入力元のXMLファイルのパス。 11 * @param string $outputC14nPath 正規化されたXMLを保存するファイルのパス。 12 * @param bool $exclusive 排他的正規化を適用するかどうか。trueの場合、名前空間の宣言が最小限になります (デフォルト: false)。 13 * @param bool $withComments コメントノードを正規化された出力に含めるかどうか (デフォルト: false)。 14 * @param ?array $xpath XPath式で正規化するノードセットを限定する場合の配列。このメソッドでは、DOMDocument全体を正規化する場合にのみ直接有効です (デフォルト: null)。 15 * @param ?array $nsPrefixes 名前空間プレフィックスのリスト。排他的正規化 (exclusive = true) の場合にのみ関連します (デフォルト: null)。 16 * @return bool 正規化が成功し、ファイルに保存できた場合はtrue、それ以外はfalse。 17 */ 18function canonicalizeXmlToFile( 19 string $inputXmlPath, 20 string $outputC14nPath, 21 bool $exclusive = false, 22 bool $withComments = false, 23 ?array $xpath = null, 24 ?array $nsPrefixes = null 25): bool { 26 // DOMDocumentオブジェクトを作成し、XMLをロードする準備をする 27 $dom = new DOMDocument(); 28 // 厳密なエラーチェックを無効にし、XMLのロードを柔軟にする 29 $dom->validateOnParse = false; 30 $dom->recover = true; // エラー回復を有効にする 31 32 // 入力XMLファイルの存在を確認 33 if (!file_exists($inputXmlPath)) { 34 echo "エラー: 入力XMLファイル '{$inputXmlPath}' が見つかりません。\n"; 35 return false; 36 } 37 38 // XMLファイルをDOMにロード 39 if (!$dom->load($inputXmlPath)) { 40 echo "エラー: XMLファイル '{$inputXmlPath}' のロードに失敗しました。\n"; 41 return false; 42 } 43 44 // DOMDocumentはDOMNodeを継承しており、C14NFileメソッドを持ちます。 45 // このメソッドはXMLを正規化し、その正規化されたXMLの文字列を返します。 46 // 引数として渡す $outputC14nPath (URI) は、このメソッド自体が直接書き込みを行うわけではなく、 47 // メソッドが返す文字列をこのパスに書き込む必要があります。 48 $c14nContent = $dom->C14NFile( 49 $outputC14nPath, // 出力先URIとしてメソッドに渡す 50 $exclusive, 51 $withComments, 52 $xpath, 53 $nsPrefixes 54 ); 55 56 // 正規化が失敗した場合 (falseが返された場合) 57 if ($c14nContent === false) { 58 echo "エラー: XMLの正規化処理に失敗しました。\n"; 59 return false; 60 } 61 62 // 正規化されたXMLコンテンツをファイルに書き込む 63 if (file_put_contents($outputC14nPath, $c14nContent) === false) { 64 echo "エラー: 正規化されたXMLをファイル '{$outputC14nPath}' に書き込めませんでした。\n"; 65 return false; 66 } 67 68 echo "XMLファイルが正規化され、'{$outputC14nPath}' に保存されました。\n"; 69 return true; 70} 71 72// ------------------------------------------------------------------------------------------------ 73// サンプルコードの実行部分 74// ------------------------------------------------------------------------------------------------ 75 76// 1. 一時的な入力XMLファイルを作成 77$inputXml = <<<XML 78<?xml version="1.0" encoding="UTF-8"?> 79<root xmlns:ns="http://example.com/ns" attrA="ValueA" attrB="ValueB"> 80 <!-- これはサンプルXMLのコメントです --> 81 <ns:element id="item1"> 82 <child>テキストコンテンツ</child> 83 </ns:element> 84 <anotherElement/> 85</root> 86XML; 87 88$inputFilePath = sys_get_temp_dir() . '/input_sample_c14n.xml'; 89file_put_contents($inputFilePath, $inputXml); 90 91// 2. 出力先の正規化されたXMLファイルのパスを定義 92$outputC14nPath = sys_get_temp_dir() . '/output_c14n_sample.xml'; 93 94// 3. XMLを正規化し、ファイルに保存 95// デフォルト設定 (コメントなし、非排他的) で正規化 96echo "--- デフォルト設定でのXML正規化の実行 ---\n"; 97$success = canonicalizeXmlToFile($inputFilePath, $outputC14nPath); 98 99if ($success) { 100 echo "\n--- 入力XMLファイルの内容 ---\n"; 101 echo file_get_contents($inputFilePath); 102 echo "\n\n--- 正規化されたXMLファイルの内容 (コメントなし) ---\n"; 103 echo file_get_contents($outputC14nPath); 104 echo "\n"; 105} 106 107// 4. コメントを含めて正規化する例 108$outputC14nWithCommentsPath = sys_get_temp_dir() . '/output_c14n_with_comments.xml'; 109echo "\n--- コメントを含めたXML正規化の実行 ---\n"; 110$successWithComments = canonicalizeXmlToFile($inputFilePath, $outputC14nWithCommentsPath, false, true); // withComments = true 111 112if ($successWithComments) { 113 echo "\n--- 正規化されたXMLファイルの内容 (コメント含む) ---\n"; 114 echo file_get_contents($outputC14nWithCommentsPath); 115 echo "\n"; 116} 117 118// 5. 一時ファイルをクリーンアップ 119if (file_exists($inputFilePath)) { 120 unlink($inputFilePath); 121} 122if (file_exists($outputC14nPath)) { 123 unlink($outputC14nPath); 124} 125if (file_exists($outputC14nWithCommentsPath)) { 126 unlink($outputC14nWithCommentsPath); 127} 128 129?>
PHP 8のDOMDocument::C14NFileメソッドは、XMLドキュメントをW3C勧告に基づくCanonical XML 1.0形式に正規化します。これは、XMLの空白や属性順序などの些細な差異をなくし、異なる環境間でもXMLの同一性を保証する重要な処理です。特にXML署名やXML暗号化など、XMLの厳密な比較が必要な場面で活用されます。
このメソッドの第一引数$uriには、正規化されたXMLを保存するファイルパスを指定します。オプションとして、$exclusive引数で排他的正規化の有無を、$withComments引数でコメントノードを含めるかを設定可能です。メソッドは、成功時に正規化されたXMLコンテンツの文字列を、失敗時にfalseを返します。サンプルコードでは、XMLファイルをDOMに読み込んだ後、このメソッドで正規化処理を実行します。そして、返された正規化済みXMLコンテンツの文字列をfile_put_contents関数でファイルに保存することで、エラー処理を含めた安全かつ確実なXML正規化とファイル出力処理を実現しています。
C14NFileメソッドは、引数で出力ファイルパスを指定しますが、これはメソッド内部で直接書き込むわけではありません。実際には正規化されたXMLの文字列を返すため、別途file_put_contents関数などを用いてファイルへの書き込みが必要です。メソッドがfalseを返した場合は正規化に失敗していますので、必ず戻り値をチェックし、適切なエラー処理を実装しましょう。DOMDocumentのvalidateOnParseやrecoverプロパティの設定によって、XMLの厳密性チェックやエラー回復の挙動が変わるため、利用するXMLの性質に合わせて適切に設定してください。このメソッドは、XMLの同一性を保証するCanonical XML(C14N)を生成するもので、XML署名などのセキュリティ関連で特に重要となります。