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

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

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

作成日: 更新日:

基本的な使い方

『C14NFileメソッドは、Dom\DocumentTypeオブジェクトが表す文書型定義ノードを正規化し、その結果を指定されたファイルに出力するメソッドです。ここで言う正規化(C14N)とは、XML文書の論理的な意味を変えることなく、その物理的な表現を標準的な形式に統一する処理を指します。これにより、例えば属性の順序や空白の扱いなどが統一され、内容が同じであれば誰が処理しても同一のバイト表現となることが保証されます。このメソッドは、出力先のファイルパスを必須の引数として受け取ります。さらに、オプションの引数を指定することで、特定の名前空間のみを対象とする排他的正規化を行うか、コメントを出力に含めるかといった詳細な動作を制御することが可能です。処理が成功した場合はファイルに書き込まれたバイト数を返し、失敗した場合はfalseを返します。主にXML署名などで文書の一貫性を厳密に検証する際、文書型定義部分の標準的な表現をファイルとして取得するために利用されます。

構文(syntax)

1<?php
2
3// DTD (文書型定義) を含むXML文字列を準備します
4$xmlString = <<<XML
5<?xml version="1.0"?>
6<!DOCTYPE root [<!ELEMENT root ANY>]>
7<root></root>
8XML;
9
10// DOMDocumentオブジェクトを作成し、XMLを読み込みます
11$doc = new DOMDocument();
12$doc->loadXML($xmlString);
13
14// XMLからDocumentTypeノードを取得します
15// $doc->doctype は Dom\DocumentType のインスタンスです
16$doctype = $doc->doctype;
17
18// DocumentTypeノードを正規化(C14N)し、その結果をファイルに保存します
19$doctype->C14NFile('output_doctype.xml');
20
21?>

引数(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メソッドは、XML文書の正規化(CANONICAL XML)をファイルに書き出す際に、書き込みが成功した場合は整数値(通常は書き込んだバイト数)、失敗した場合はfalseを返します。

サンプルコード

PHP C14NFileでXMLを正規化する

1<?php
2
3/**
4 * XMLドキュメントを正規化(Canonicalization)し、指定されたファイルに保存する関数。
5 *
6 * この関数はDOMDocumentクラスのC14NFileメソッドを使用します。
7 * C14Nは、XMLドキュメントの物理的な表現に関わらず、論理的に同一のドキュメントを
8 * 常に同じバイト列に変換するプロセスです。これは主にXML署名などで利用されます。
9 *
10 * @param string $xmlContent 正規化するXMLの文字列データ。
11 * @param string $outputFilePath 正規化されたXMLを保存するファイルのパス。
12 * @param bool $exclusive 排他的なC14Nを使用するかどうか。trueの場合、排他的な正規化が行われます。
13 * @param bool $withComments コメントを正規化された出力に含めるかどうか。trueの場合、コメントも出力されます。
14 * @param ?array $xpath XPath式を要素の配列として指定することで、正規化の対象を特定できます。
15 *                       指定しない場合、ドキュメント全体が対象となります。
16 * @param ?array $nsPrefixes 名前空間プレフィックスの配列を指定します。
17 * @return int|false 成功した場合は書き込まれたバイト数、失敗した場合は false を返します。
18 */
19function canonicalizeAndSaveXmlToFile(
20    string $xmlContent,
21    string $outputFilePath,
22    bool $exclusive = false,
23    bool $withComments = false,
24    ?array $xpath = null,
25    ?array $nsPrefixes = null
26): int|false {
27    // 新しいDOMDocumentオブジェクトを作成します。
28    // PHP 8では、XML正規化機能は主にDOMDocumentクラスで提供されます。
29    $dom = new DOMDocument('1.0', 'UTF-8');
30
31    // 空白ノードを無視することで、より予測可能な正規化結果が得られることがあります。
32    $dom->preserveWhiteSpace = false;
33    // 出力時にXMLを整形するかどうか。C14Nの出力自体には影響しません。
34    $dom->formatOutput = true; 
35
36    // XML文字列をDOMドキュメントにロードします。
37    // ロードに失敗した場合は処理を中断します。
38    if (!@$dom->loadXML($xmlContent)) {
39        error_log("Error: Failed to load XML content.");
40        return false;
41    }
42
43    // DOMDocument::C14NFileメソッドを呼び出してXMLを正規化し、ファイルに保存します。
44    // $uri (ファイルパス), $exclusive, $withComments, $xpath, $nsPrefixes の引数を渡します。
45    $bytesWritten = $dom->C14NFile(
46        $outputFilePath,
47        $exclusive,
48        $withComments,
49        $xpath,
50        $nsPrefixes
51    );
52
53    // 戻り値を確認し、結果を出力します。
54    if ($bytesWritten !== false) {
55        echo "XMLを正規化し、'{$outputFilePath}' に保存しました。書き込まれたバイト数: {$bytesWritten}\n";
56    } else {
57        error_log("Error: XMLの正規化とファイルへの保存に失敗しました。");
58    }
59
60    return $bytesWritten;
61}
62
63// --- サンプルコードの実行 ---
64
65// 正規化するXMLコンテンツの例
66$sampleXml = <<<XML
67<?xml version="1.0" encoding="UTF-8"?>
68<root attr1="value1" attr2="value2">
69    <element>
70        <!-- これはコメントです -->
71        Hello, World!
72    </element>
73    <anotherElement/>
74</root>
75XML;
76
77// 出力先のファイルパス
78$outputFile = 'canonicalized_output.xml';
79
80// 関数を呼び出してXMLを正規化し、ファイルに保存します。
81// 例として、排他的なC14Nは使用せず、コメントは含める設定で実行します。
82$result = canonicalizeAndSaveXmlToFile(
83    $sampleXml,
84    $outputFile,
85    $exclusive = false,
86    $withComments = true
87);
88
89if ($result !== false) {
90    echo "正規化されたXMLファイルが '{$outputFile}' に作成されました。内容を確認してください。\n";
91    // 必要であれば、作成されたファイルの内容を表示することもできます。
92    // echo "\n--- File Content ---\n";
93    // echo file_get_contents($outputFile);
94    // echo "\n--------------------\n";
95}
96
97// サンプル実行後に生成されたファイルを自動的にクリーンアップします。
98register_shutdown_function(function() use ($outputFile) {
99    if (file_exists($outputFile)) {
100        unlink($outputFile);
101        echo "クリーンアップ: '{$outputFile}' を削除しました。\n";
102    }
103});
104
105?>

このコードは、PHP 8でXMLドキュメントを正規化し、その結果を指定されたファイルに保存する方法を示すものです。XMLの正規化(Canonicalization、略してC14N)とは、XMLドキュメントの物理的な表現が異なっていても、論理的に同じ内容であれば常に同一のバイト列に変換するプロセスを指します。これは、XML署名などでドキュメントの改ざんを確実に検出するために重要な技術です。

サンプルコードでは、PHPのDOMDocumentクラスが提供するC14NFileメソッドを利用しています。このメソッドは、現在のDOMDocumentオブジェクトにロードされているXMLを正規化し、第一引数で指定されたファイルパス($uri)に結果を書き込みます。第二引数の$exclusiveには排他的な正規化を行うかを、第三引数の$withCommentsにはコメントを含めるかを真偽値で渡します。オプションとして$xpath$nsPrefixesを指定することで、正規化の対象範囲を細かく指定することも可能です。

C14NFileメソッドの戻り値は、処理が成功した場合は書き込まれたバイト数を示す整数値で、失敗した場合はfalseを返します。コードの実行例では、まず指定されたXML文字列をDOMDocumentオブジェクトにロードし、その後C14NFileメソッドを呼び出して正規化されたXMLをcanonicalized_output.xmlというファイルに保存しています。処理の成否に応じて適切なメッセージが出力され、最終的に生成されたファイルは自動的に削除されます。

このサンプルコードは、XMLドキュメントを正規化(C14N)し、その結果を指定されたファイルに保存する方法を示しています。C14NFileメソッドはDOMDocumentクラスの機能であり、利用する前にDOMDocumentオブジェクトを作成し、loadXMLメソッドでXMLデータを適切に読み込む必要があります。loadXMLが失敗した場合はfalseが返されるため、必ずエラーハンドリングを行ってください。

C14NFileメソッドの第一引数に指定するファイルパスは、PHPが書き込み権限を持つ場所である必要があります。また、$exclusive$withComments$xpathなどの引数は正規化の挙動に大きく影響しますので、XML署名など利用目的に合わせてそれぞれの意味を正確に理解し、適切に設定することが重要です。メソッドの戻り値は書き込まれたバイト数かfalseなので、処理の成否を必ず確認し、失敗時の適切なエラー処理を記述することが安全なコード利用につながります。

PHP Dom C14NFile でXMLを正規化する

1<?php
2
3// Dom\Document::C14NFile は、XML ドキュメントの正規化された表現を指定されたファイルに書き出すメソッドです。
4// これは実質的に、XML データの一部または全体を正規化して新しいファイルに「コピー」(保存)する操作と見なせます。
5// Dom\Document は Dom\Node を継承しており、このメソッドを利用できます。
6
7/**
8 * サンプルXMLドキュメントを正規化してファイルに保存するプロセスを示します。
9 * この関数は、システムエンジニアを目指す初心者がXMLの正規化とファイル操作を理解するのに役立ちます。
10 *
11 * @return void
12 */
13function demonstrateXmlC14nFile(): void
14{
15    // 出力先のファイルパスを定義します。
16    // __DIR__ は現在のスクリプトファイルがあるディレクトリを指します。
17    $outputFile = __DIR__ . '/canonicalized_document.xml';
18
19    // PHP 8 の新しい Dom 拡張機能を使用して Dom\Document オブジェクトを作成します。
20    $document = new Dom\Document('1.0', 'UTF-8');
21
22    // サンプルXMLコンテンツをロードします。
23    // <?xml ... ?> 宣言は loadXML メソッドによって自動的に処理されるため、
24    // ここではルート要素から記述しています。
25    $document->loadXML(<<<XML
26<root attribute="value">
27    <element>
28        これはテキストデータです。
29        <!-- これはコメントです。正規化時に含めることができます。 -->
30    </element>
31    <anotherElement xmlns:p="http://example.com/ns">
32        <p:childNode/>
33    </anotherElement>
34</root>
35XML);
36
37    echo "XMLドキュメントを正規化してファイルに書き込みます: {$outputFile}\n";
38
39    try {
40        // C14NFile メソッドを呼び出して、ドキュメント全体を正規化しファイルに書き出します。
41        // 第1引数: 書き出すファイルのURI(パス)を指定します。
42        // 第2引数: exclusive (排他的正規化) を指定します。false で通常の正規化を行います。
43        // 第3引数: withComments (コメントを含めるか) を指定します。true でコメントを含めます。
44        $bytesWritten = $document->C14NFile($outputFile, false, true);
45
46        if ($bytesWritten !== false) {
47            echo "正規化されたXMLがファイルに正常に書き込まれました。\n";
48            echo "書き込まれたバイト数: {$bytesWritten}\n";
49            echo "ファイル '{$outputFile}' の内容を確認してください。\n";
50            echo "例: コマンドラインで 'cat {$outputFile}' を実行。\n";
51        } else {
52            echo "エラー: 正規化されたXMLのファイルへの書き込みに失敗しました。\n";
53        }
54    } catch (Dom\Exception $e) {
55        // DOM関連の操作中に発生したエラーを捕捉します。
56        echo "DOM操作中にエラーが発生しました: " . $e->getMessage() . "\n";
57    } catch (Throwable $e) {
58        // その他の予期せぬエラーを捕捉します。
59        echo "予期せぬエラーが発生しました: " . $e->getMessage() . "\n";
60    } finally {
61        // スクリプトの実行後、作成された一時ファイルを削除するオプション(コメントアウトされています)。
62        // 初心者の学習のため、まずはファイル内容を確認できるよう残しておくことを推奨します。
63        // 必要に応じて以下のコメントを解除してファイルを削除してください。
64        // if (file_exists($outputFile)) {
65        //     unlink($outputFile);
66        //     echo "一時ファイル '{$outputFile}' を削除しました。\n";
67        // }
68    }
69}
70
71// 上記の関数を実行して、XML正規化のデモンストレーションを開始します。
72demonstrateXmlC14nFile();
73
74?>

このサンプルコードは、PHP 8のDom拡張機能を利用してXMLドキュメントを正規化し、ファイルに保存する方法を示しています。Dom\DocumentクラスのC14NFileメソッドは、XMLドキュメントの内容を標準的な形式(正規形)に変換した上で、その結果を指定されたファイルに書き出す機能を提供します。これは、XMLデータの厳密な比較やデジタル署名の生成などにおいて重要な処理です。

コードではまず、Dom\Documentオブジェクトを作成し、loadXMLメソッドでサンプルXML文字列を読み込んでいます。その後、C14NFileメソッドを呼び出して正規化処理とファイルへの書き出しを実行します。第一引数$uriには、正規化されたXMLを保存するファイルパスを指定します。第二引数$exclusiveは排他的正規化を行うかどうかを決定し、falseで通常の正規化を行います。第三引数$withCommentsは、コメントを正規化結果に含めるかどうかを真偽値で指定し、trueとすることでコメントも出力されます。

C14NFileメソッドの戻り値は、書き込みが成功した場合には書き込まれたバイト数(整数)を返し、失敗した場合にはfalseを返します。サンプルコードはこの戻り値を確認し、成功または失敗に応じたメッセージを表示します。また、XML操作中に発生する可能性のあるエラーを捕捉するための例外処理も含まれており、堅牢なプログラムの記述方法も学ぶことができます。

Dom\Document::C14NFileメソッドは、XMLドキュメントを正規化し、その結果を指定されたファイルに保存します。これは、XMLデータを正規化して新しいファイルに安全に「コピー」する操作と理解できます。

リファレンス情報ではDom\DocumentTypeのメソッドとありますが、PHP 8の新Dom拡張ではDom\Documentクラスのメソッドとして利用できる点にご留意ください。出力先のファイルパスには、スクリプトが書き込み権限を持つ場所を指定してください。

このメソッドは、成功時に書き込まれたバイト数を、失敗時にfalseを返します。そのため、必ず戻り値がfalseでないか確認し、エラーハンドリングを適切に実装することが重要です。特にDom\Exceptionを捕捉することで、XML操作固有のエラーに対応できます。

関連コンテンツ

関連IT用語

関連プログラミング言語