Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】DOMNotation::C14NFile()メソッドの使い方

C14NFileメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

DOMNotationクラスのC14NFileメソッドは、指定されたノードをW3C勧告の「Canonical XML Version 1.1」に従って、XMLドキュメントの正規化(Canonicalization)を行い、その結果を指定されたファイルに保存するメソッドです。このメソッドは、XML文書の一部分木を、プラットフォームやエンコーディングに依存しない一貫した形式に変換するために使用されます。

具体的には、指定されたノードから始まるXML文書を正規化し、その結果を引数で指定されたファイルパスに保存します。正規化処理には、属性の並び替え、名前空間宣言の整理、コメントの削除、空白の正規化などが含まれます。

このメソッドは、XML文書のデジタル署名や、XML文書の比較、XML文書のキャッシュなど、さまざまな場面で役立ちます。異なる環境で生成されたXML文書を比較したり、同じXML文書であるかどうかを検証したりする場合に、正規化処理を行うことで、プラットフォームやエンコーディングの違いによる影響を排除し、正確な比較が可能になります。

C14NFileメソッドを使用することで、XML文書の相互運用性を高め、データの一貫性を保つことができます。システムエンジニアは、このメソッドを利用することで、XML文書を扱うアプリケーションの信頼性と安定性を向上させることができます。引数には、正規化するノードと、出力先のファイルパスを指定します。ファイルパスが存在しない場合は、新たにファイルが作成されます。

構文(syntax)

1$notation->C14NFile(
2    uri: 'path/to/save.xml',
3    exclusive: false,
4    withComments: false,
5    xpath: null,
6    nsPrefixes: false
7);

引数(parameters)

string $uri, bool $exclusive = false, bool $withComments = false, ?array $xpath = null, ?array $nsPrefixes = null

  • string $uri: Canonicalize (正規化) するXMLファイルまたはDOMDocumentオブジェクトのURIを指定します。
  • bool $exclusive = false: falseの場合、すべてのノードが正規化されます。trueの場合、指定されたXPath式に一致するノードのみが正規化されます。
  • bool $withComments = false: trueの場合、コメントノードも正規化に含まれます。
  • ?array $xpath = null: $exclusive が true の場合に、正規化の対象とするノードを指定するXPath式の配列です。
  • ?array $nsPrefixes = null: 名前空間のプレフィックスをマッピングする連想配列です。

戻り値(return)

bool

DOMDocument::C14NFile メソッドは、XML 文書を正規化してファイルに保存する操作が成功したかどうかを示す真偽値を返します。成功した場合は true を、失敗した場合は false を返します。

サンプルコード

PHP DOM C14NFileでXML正規化する

1<?php
2
3/**
4 * PHP DOM extensionの例:XMLの正規化(C14N)をファイルに書き出すデモンストレーション。
5 *
6 * このコードは、XMLドキュメントを正規化し、その結果を指定されたファイルに書き出す
7 * `C14NFile`メソッドの使用方法を示しています。
8 *
9 * 注意点:
10 * 提供されたリファレンス情報では「所属クラス: DOMNotation」と指定されていますが、
11 * 標準のPHP DOM拡張において、XML正規化を行う`C14NFile`メソッドは
12 * `DOMDocument`クラスに属しています。`DOMNotation`オブジェクトはDTDの記法を表し、
13 * ドキュメントレベルの正規化操作は行いません。
14 *
15 * そのため、このサンプルコードでは、提供されたメソッドシグネチャ(引数と戻り値)に
16 * 合致し、かつPHPで実際に機能する`DOMDocument::C14NFile`メソッドを使用しています。
17 * これにより、システムエンジニアを目指す初心者の方にも、正確で動作するC14Nの例を提供します。
18 */
19function demonstrateC14NFile(): void
20{
21    // 1. サンプルとなるXMLドキュメントを作成します。
22    //    C14Nの動作(コメントの削除、空白の正規化など)を示すため、
23    //    コメントや名前空間、余分な空白を含むシンプルなXMLを使用します。
24    $xmlString = <<<XML
25<?xml version="1.0" encoding="UTF-8"?>
26<root xmlns:my="http://example.com/ns">
27    <!-- これは正規化によって削除されるコメントです -->
28    <element id="1">
29        Hello
30        <child attr="value"/>
31    </element>
32    <my:other_element>World</my:other_element>
33</root>
34XML;
35
36    // 2. XMLをDOMDocumentオブジェクトにロードします。
37    $dom = new DOMDocument('1.0', 'UTF-8');
38    // `preserveWhiteSpace` を `false` に設定することで、C14Nの出力が一貫しやすくなります。
39    $dom->preserveWhiteSpace = false;
40    // XML文字列をDOMDocumentにロードします。
41    $dom->loadXML($xmlString);
42
43    // 3. 正規化されたXMLを書き出すための一時ファイルパスを定義します。
44    $outputFile = __DIR__ . '/canonicalized_output.xml';
45
46    // 4. XMLを正規化し、指定されたファイルに書き出します。
47    //    引数の定義: string $uri, bool $exclusive = false, bool $withComments = false, ?array $xpath = null, ?array $nsPrefixes = null
48    //    ここでは、最も基本的なC14N形式(排他的C14Nではない、コメントを含まない)で実行します。
49    $success = $dom->C14NFile(
50        $outputFile,        // $uri: 正規化されたXMLを書き出すファイルパス
51        false,              // $exclusive: 排他的C14Nを使用しない(デフォルトのC14N 1.0)
52        false,              // $withComments: コメントを正規化された出力に含めない
53        null,               // $xpath: 特定のノードセットに限定しない(ドキュメント全体を対象)
54        null                // $nsPrefixes: 特定の名前空間プレフィックスに限定しない
55    );
56
57    // 5. 正規化の成功/失敗をチェックし、結果を表示します。
58    if ($success) {
59        echo "XMLは正常に正規化され、ファイルに書き込まれました: {$outputFile}\n";
60        echo "\n--- canonicalized_output.xml の内容 ---\n";
61        echo file_get_contents($outputFile);
62        echo "---------------------------------------\n";
63    } else {
64        echo "XMLの正規化に失敗しました。\n";
65    }
66
67    // 6. 生成された一時ファイルをクリーンアップします。
68    if (file_exists($outputFile)) {
69        unlink($outputFile);
70        echo "\n{$outputFile} をクリーンアップしました。\n";
71    }
72}
73
74// 上記のデモンストレーション関数を実行します。
75demonstrateC14NFile();

PHPのDOMDocument::C14NFileメソッドは、XMLドキュメントを正規化し、その結果を指定されたファイルに書き出すために使用されます。正規化(C14N)とは、XMLの論理的な内容を変えずに、その物理的な表現を標準的な形式に変換するプロセスです。これにより、異なるXMLドキュメントが論理的に同じであるかどうかの比較が容易になります。

提供されたリファレンス情報では「DOMNotation」に属するとされていますが、実際にはDOMDocumentクラスのメソッドです。サンプルコードは、まずXML文字列をDOMDocumentオブジェクトとしてロードし、その後C14NFileメソッドを使って正規化されたXMLを「canonicalized_output.xml」というファイルに保存する一連の流れを示しています。

このメソッドは、第一引数$uriで出力先のファイルパスを指定します。$exclusivetrueに設定すると排他的C14Nが適用され、$withCommentstrueに設定するとコメントが正規化された出力に含まれます。$xpath$nsPrefixesを使えば、ドキュメント全体ではなく特定のノードセットや名前空間に限定した正規化も可能です。メソッドは処理が成功すればtrueを、失敗すればfalseを返します。この機能は、XMLのデジタル署名や比較など、XMLの厳密な同一性を保証する必要がある場面で特に役立ちます。

提供されたリファレンスではDOMNotationクラスに属するとありますが、このC14NFileメソッドはPHPの標準的なDOM拡張においてDOMDocumentクラスに属しますのでご注意ください。サンプルコードは正しい利用法を示しています。

C14NFileは指定されたファイルに正規化されたXMLを書き出すため、スクリプトの実行環境には書き込み権限が必要です。権限がない場合、処理が失敗します。XML正規化(C14N)は、コメントや余分な空白などを削除し、一貫した形式に変換する操作です。引数$withCommentsでコメントの出力有無を制御できますので、必要に応じて設定してください。また、DOMDocumentpreserveWhiteSpaceプロパティをfalseに設定すると、C14Nの出力結果がより安定します。生成された一時ファイルは必ず適切に管理し、不要な場合は削除するように心がけてください。

PHPでXMLを正規化しファイル保存する

1<?php
2
3/**
4 * XMLドキュメントを正規化(Canonicalization)し、指定されたファイルに保存します。
5 *
6 * この関数は、XMLドキュメントのDOM表現に対してC14NFileメソッドを呼び出します。
7 * C14N (Canonical XML) は、XMLドキュメントを比較可能で一貫性のある形式に変換する標準です。
8 * DOMDocumentクラスはDOMNodeを継承しているため、DOMNode::C14NFileメソッドを使用できます。
9 *
10 * @param string $xmlContent 正規化するXML文字列。
11 * @param string $outputPath 正規化されたXMLを保存するファイルのパス。
12 * @param bool $exclusive 排他的C14N (Exclusive Canonicalization) を使用するかどうか。
13 *                         false の場合、標準C14Nを使用します。
14 *                         デフォルトは false。
15 * @param bool $withComments コメントノードを正規化された出力に含めるかどうか。
16 *                            デフォルトは false。
17 * @param ?array $xpath XPath式に一致するノードのみを対象とするための配列。
18 *                       null の場合、ドキュメント全体を対象とします。デフォルトは null。
19 * @param ?array $nsPrefixes XPathと組み合わせて、特定の名前空間プレフィックスの宣言を含めるための配列。
20 *                            null の場合、デフォルトの動作を使用します。デフォルトは null。
21 * @return bool 正規化とファイルへの保存が成功した場合は true、それ以外は false。
22 */
23function generateCanonicalXmlFile(
24    string $xmlContent,
25    string $outputPath,
26    bool $exclusive = false,
27    bool $withComments = false,
28    ?array $xpath = null,
29    ?array $nsPrefixes = null
30): bool {
31    // 新しいDOMDocumentオブジェクトを作成
32    $dom = new DOMDocument('1.0', 'UTF-8');
33    // エラーハンドリングを強化するため、libxmlエラーを抑制し、後で取得します。
34    libxml_use_internal_errors(true);
35
36    // XML文字列をDOMオブジェクトにロード
37    if (!$dom->loadXML($xmlContent)) {
38        // XMLロード失敗時のエラーメッセージを表示
39        echo "エラー: XMLのロードに失敗しました。\n";
40        foreach (libxml_get_errors() as $error) {
41            echo "  " . $error->message;
42        }
43        libxml_clear_errors(); // エラーをクリア
44        return false;
45    }
46    libxml_clear_errors(); // 成功した場合もエラーをクリア
47
48    // XMLを正規化し、指定されたファイルに保存
49    // DOMDocumentはDOMNodeを継承しており、C14NFileメソッドはDOMNodeのメソッドです。
50    // 提供されたリファレンスの引数リストと一致します。
51    $success = $dom->C14NFile($outputPath, $exclusive, $withComments, $xpath, $nsPrefixes);
52
53    if ($success) {
54        echo "正規化されたXMLがファイル '{$outputPath}' に正常に保存されました。\n";
55        return true;
56    } else {
57        echo "エラー: XMLの正規化とファイルへの保存に失敗しました。\n";
58        return false;
59    }
60}
61
62// --- サンプルコードの実行 ---
63
64// 正規化するXMLコンテンツの例
65$sampleXml = <<<XML
66<?xml version="1.0" encoding="UTF-8"?>
67<root xmlns:ns="http://example.com/ns">
68    <!-- これはコメントです -->
69    <element attribute="value">
70        <child>テキストコンテンツ</child>
71    </element>
72    <ns:otherElement/>
73</root>
74XML;
75
76// 一時ファイルパスを生成 (システムの一時ディレクトリを使用)
77$outputFileBase = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'canonical_output_';
78
79echo "--- 通常の正規化(コメントなし) ---\n";
80$outputFileDefault = $outputFileBase . 'default.xml';
81// デフォルトの正規化を実行(排他的C14Nなし、コメントなし)
82if (generateCanonicalXmlFile($sampleXml, $outputFileDefault)) {
83    echo "出力内容:\n";
84    echo htmlspecialchars(file_get_contents($outputFileDefault)) . "\n\n";
85    unlink($outputFileDefault); // 生成したファイルを削除
86}
87
88echo "--- コメントを含む正規化 ---\n";
89$outputFileWithComments = $outputFileBase . 'with_comments.xml';
90// コメントを含む正規化を実行
91if (generateCanonicalXmlFile($sampleXml, $outputFileWithComments, false, true)) {
92    echo "出力内容:\n";
93    echo htmlspecialchars(file_get_contents($outputFileWithComments)) . "\n\n";
94    unlink($outputFileWithComments); // 生成したファイルを削除
95}
96
97echo "--- 排他的正規化(コメントなし) ---\n";
98$outputFileExclusive = $outputFileBase . 'exclusive.xml';
99// 排他的C14Nを実行(コメントなし)
100// 排他的C14Nでは、名前空間の宣言がルート要素ではなく、それを参照する要素に直接記述されることがあります。
101// また、不要な名前空間宣言が省略されることがあります。
102if (generateCanonicalXmlFile($sampleXml, $outputFileExclusive, true, false)) {
103    echo "出力内容:\n";
104    echo htmlspecialchars(file_get_contents($outputFileExclusive)) . "\n\n";
105    unlink($outputFileExclusive); // 生成したファイルを削除
106}

PHP 8のDOMNotationクラスに属するとされるC14NFileメソッドは、XMLドキュメントをCanonical XML(C14N)と呼ばれる標準形式で正規化し、その結果を指定したファイルに保存する機能を提供します。C14Nとは、XMLドキュメントの内容に意味的な変更を加えることなく、比較可能で一貫性のある形式に変換するための標準です。この機能は、XMLドキュメントの同一性を比較したり、署名などで利用したりする場合に役立ちます。

このメソッドは、XMLドキュメントのDOM表現を扱うDOMDocumentクラスのオブジェクトから呼び出すことができます。これはDOMDocumentDOMNodeを継承しており、C14NFileメソッドはDOMNodeのメソッドとして提供されているためです。

引数には、まず正規化されたXMLを保存するファイルパスを$uriとして指定します。$exclusivetrueにすると排他的C14Nが適用され、名前空間の宣言方法が通常と異なります。$withCommentsは、XML内のコメントノードを正規化された出力に含めるかどうかをtrueまたはfalseで指定します。$xpath$nsPrefixesはオプションで、ドキュメント全体ではなく、XPath式に一致する特定のノードだけを対象としたり、特定の名前空間プレフィックスの宣言を含めたりする場合に利用します。

このメソッドは、正規化とファイルへの保存処理が成功した場合はtrueを、何らかの理由で失敗した場合はfalseを戻り値として返します。サンプルコードでは、様々なオプションでXMLを正規化し、ファイルに保存する具体的な手順を示しており、出力内容から正規化の違いを確認できます。

このサンプルコードで利用しているC14NFileメソッドは、XMLドキュメントの正規化を行い、指定したファイルに保存します。このメソッドはDOMDocumentオブジェクトから呼び出すことが一般的です。ファイルパス($outputPath)には書き込み権限のある有効な場所を指定してください。XMLのロードや正規化処理が失敗した場合、メソッドはfalseを返しますので、必ずその戻り値を確認し、適切なエラー処理を実装することが重要です。特にlibxml_use_internal_errors()でエラー処理を有効にした場合は、処理後にlibxml_clear_errors()を呼び出し、エラーバッファをクリアするようにしてください。xpathnsPrefixesといった引数は特定のノードを対象とするための高度なオプションですので、通常はデフォルト値(null)で問題ありません。この正規化処理はXMLの比較やデジタル署名といった場面で特に役立ちます。

関連コンテンツ

関連IT用語

関連プログラミング言語