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

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

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

作成日: 更新日:

基本的な使い方

Dom\NotationクラスのC14NFileメソッドは、ノードをCanonical XML(C14N)形式でファイルにシリアライズするメソッドです。C14Nは、XMLドキュメントを正規化するための標準規格であり、XMLドキュメントの内容が変わらない限り、表現形式の違いを吸収して一意な形式に変換することを目的としています。このメソッドを使用することで、Dom\Notationノードの内容をC14N形式でファイルに保存できます。

具体的には、C14NFileメソッドは、指定されたノードをC14N形式に変換し、その結果を指定されたファイルパスに書き込みます。この処理は、XMLデータの整合性を保証したり、異なるシステム間でXMLデータを交換する際に役立ちます。たとえば、デジタル署名を作成する前にXMLドキュメントを正規化することで、署名の検証を確実に行うことができます。

C14NFileメソッドは、ファイルパスを引数として受け取ります。必要に応じて、C14Nのバージョンや、コメントの保持、空のノードの処理方法などを制御するためのオプションを指定することも可能です。C14NFileメソッドを使用することで、Dom\Notationノードを簡単にCanonical XML形式でファイルに保存し、XMLデータの相互運用性を高めることができます。システムエンジニアは、このメソッドを利用することで、XMLデータを扱うアプリケーションにおいて、データの整合性や互換性を確保することができます。

構文(syntax)

1Dom\Notation::C14NFile( ?string $uri, bool $exclusive = false, bool $with_comments = false, ?array $xpath = null, ?string $nsPrefixes = null ): int|false

引数(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の場合、XMLコメントも正規化に含めます。
  • ?array $xpath = null: 正規化する要素を指定するXPath式の配列です。
  • ?array $nsPrefixes = null: 名前空間のプレフィックスとURIの対応を指定する配列です。

戻り値(return)

int|false

C14NFileメソッドは、XML文書を正規化してファイルに保存し、成功した場合は1、失敗した場合はfalseを返します。

サンプルコード

PHP DOM XML正規化 (C14N) をファイルに保存する

1<?php
2
3/**
4 * このスクリプトは、PHPのDOM拡張機能を使用してXMLドキュメントを正規化(Canonicalization, C14N)し、
5 * その結果をファイルに保存する方法を示します。
6 *
7 * 正規化は、同じ論理内容を持つXMLドキュメントを常に同じバイト列に変換するプロセスであり、
8 * 特にXML署名などのセキュリティ関連の機能で重要になります。
9 *
10 * 提供されたリファレンス情報では「Dom\Notation::C14NFile」と指定されていましたが、
11 * PHPのDOM拡張においてC14NFileメソッドは実際にはDOMDocumentクラスに属します。
12 * したがって、このサンプルコードではDOMDocument::C14NFile() を使用しています。
13 */
14function demonstrateC14NFile(): void
15{
16    // 1. 正規化したい簡単なXMLドキュメントを準備します。
17    //    コメントや異なる形式の改行などが含まれていても、正規化によって統一されます。
18    $originalXmlString = <<<XML
19<?xml version="1.0" encoding="UTF-8"?>
20<root xmlns:my="http://example.com/ns">
21    <!-- これはコメントです -->
22    <element attr="value">
23        こんにちは、世界!
24    </element>
25    <my:child/>
26</root>
27XML;
28
29    // 2. DOMDocument オブジェクトを作成し、XML文字列をロードします。
30    $dom = new DOMDocument();
31    $dom->loadXML($originalXmlString);
32
33    // 3. 正規化されたXMLを保存するファイルパスを定義します。
34    //    __DIR__ は現在のスクリプトが置かれているディレクトリを指します。
35    $outputFilePath = __DIR__ . '/canonicalized_output.xml';
36
37    echo "--- 元のXMLドキュメント ---\n";
38    echo $dom->saveXML();
39    echo "\n---------------------------\n";
40    echo "XMLを正規化し、ファイルに書き込みます: {$outputFilePath}\n";
41
42    // 4. DOMDocument::C14NFile() メソッドを呼び出してXMLを正規化し、ファイルに保存します。
43    //    引数:
44    //    - $uri: 出力ファイルのパス (string)
45    //    - $exclusive: 排他的正規化を行うか (false = 包括的正規化, true = 排他的正規化)
46    //                  デフォルトはfalse(包括的正規化)
47    //    - $withComments: コメントを含めるか (false = 含めない, true = 含める)
48    //                    デフォルトはfalse(含めない)
49    //    - $xpath: 正規化するノードを絞り込むXPath式の配列 (null = ドキュメント全体)
50    //    - $nsPrefixes: 名前空間のプレフィックスの配列 (null = ドキュメントの名前空間を使用)
51    //
52    //    この例では、最も一般的な包括的正規化(コメントなし、ドキュメント全体)を行います。
53    $bytesWritten = $dom->C14NFile($outputFilePath, false, false, null, null);
54
55    // 5. メソッドの戻り値 (書き込まれたバイト数、または失敗時のfalse) を確認し、結果を表示します。
56    if ($bytesWritten === false) {
57        echo "エラー: XMLの正規化とファイルへの書き込みに失敗しました。\n";
58    } else {
59        echo "成功: XMLが正規化され、{$bytesWritten} バイトが '{$outputFilePath}' に書き込まれました。\n";
60
61        // 生成されたファイルの内容を読み込んで表示し、正規化の結果を確認します。
62        if (file_exists($outputFilePath)) {
63            echo "\n--- 生成された正規化済みXMLファイルの内容 ---\n";
64            echo file_get_contents($outputFilePath);
65            echo "\n-------------------------------------------\n";
66
67            // 必要に応じて、テスト後にファイルを削除することができます。
68            // unlink($outputFilePath);
69        }
70    }
71}
72
73// 関数を実行してサンプルコードの動作を確認します。
74demonstrateC14NFile();
75

DOMDocument::C14NFile() メソッドは、XMLドキュメントを正規化(Canonicalization, C14N)し、その結果を指定されたファイルに保存する機能を提供します。正規化は、同じ論理内容を持つXMLを常に同じバイト列に変換するプロセスであり、XML署名などのセキュリティ関連機能において特に重要となります。

このメソッドはDOMDocumentオブジェクトに対して呼び出され、最初の引数$uriに出力先のファイルパスを指定します。$exclusive引数には、排他的正規化を行うかどうかの真偽値(falseで包括的正規化、trueで排他的正規化)を渡します。$withComments引数は、正規化された出力にXMLコメントを含めるかどうかを真偽値で指定します。また、オプションの$xpath$nsPrefixes引数を使用すると、正規化の対象ノードや名前空間の扱いをより詳細に制御できます。

メソッドは成功した場合、ファイルに書き込まれたバイト数を整数で返しますが、処理が失敗した場合にはfalseを返します。そのため、戻り値を確認して適切なエラー処理を行うことが重要です。サンプルコードでは、簡単なXMLドキュメントを読み込み、包括的正規化(コメントなし)を行った結果をファイルに保存し、その内容を表示する一連の流れを確認できます。

このサンプルコードはXMLの正規化(C14N)をファイルへ保存する例です。リファレンス情報ではDom\Notation::C14NFileとありますが、PHP 8のDOM拡張ではDOMDocument::C14NFile()メソッドとして利用するのが一般的ですのでご注意ください。出力ファイルパス$uriは、スクリプトが書き込み可能なディレクトリを指定してください。メソッドは成功すると書き込んだバイト数を、失敗するとfalseを返すため、必ず=== falseで厳密に確認し、適切なエラーハンドリングを実装することが重要です。$exclusive$withCommentsなどの引数は、正規化の具体的な挙動を制御し、出力結果に影響しますので、目的に応じて適切に設定してください。

PHPでXMLを正規化しコピーする

1<?php
2
3// Dom\Notation クラスと C14NFile メソッドについて:
4// PHP 8のDom\Notationクラス自体には、C14NFileメソッドは直接定義されていません。
5// C14NFileメソッドは、主にDOMDocumentクラスやDOMElementクラスで使用され、
6// XMLドキュメント全体または特定のXMLノードをCanonical XML (C14N) 形式で
7// ファイルに保存するために利用されます。
8//
9// しかし、Dom\NotationはXMLのDTDの一部であり、DOMDocumentが扱うXMLドキュメントの
10// 内部に含まれる可能性のある要素です。
11// このサンプルコードでは、Dom\Notationを含む可能性のあるXMLドキュメント全体を対象に、
12// DOMDocument::C14NFile を用いて正規化しファイルに保存する(「コピー」する)例を示します。
13// これは、キーワード「php cp」(コピー)の意図に沿いつつ、C14NFileの機能を示すものです。
14
15/**
16 * 一時的なXMLファイルを作成し、指定されたコンテンツを書き込みます。
17 *
18 * @param string $content 書き込むXMLコンテンツ。
19 * @return string 作成された一時ファイルのパス。
20 * @throws RuntimeException ファイル作成または書き込みに失敗した場合。
21 */
22function createTempXmlFile(string $content): string
23{
24    // 一時ファイル名の生成
25    $tempFile = tempnam(sys_get_temp_dir(), 'xml_input_');
26    if ($tempFile === false) {
27        throw new RuntimeException('一時ファイルの作成に失敗しました。');
28    }
29
30    // コンテンツを一時ファイルに書き込み
31    if (file_put_contents($tempFile, $content) === false) {
32        // 書き込み失敗時に一時ファイルを削除
33        unlink($tempFile); 
34        throw new RuntimeException('一時ファイルへのコンテンツ書き込みに失敗しました。');
35    }
36    return $tempFile;
37}
38
39/**
40 * XMLコンテンツをCanonical XML (C14N) 形式に正規化し、新しいファイルに保存します。
41 *
42 * この関数は、入力されたXMLコンテンツをDOMDocumentオブジェクトで処理し、
43 * Canonical XML (C14N) 形式で出力ファイルに保存します。
44 * これは実質的に、正規化されたXMLを新しいファイルに「コピー (cp)」する操作と見なせます。
45 *
46 * @param string $inputXmlContent 正規化するXMLの文字列。
47 * @param string $outputFilePath 正規化されたXMLを保存するファイルパス。
48 * @return bool 処理が成功した場合は true、失敗した場合は false。
49 */
50function canonicalizeAndSaveXml(string $inputXmlContent, string $outputFilePath): bool
51{
52    $inputTempFile = null;
53    try {
54        // 入力XMLコンテンツを一時ファイルに保存し、DOMDocumentで読み込めるようにします。
55        $inputTempFile = createTempXmlFile($inputXmlContent);
56
57        // DOMDocument オブジェクトを初期化します。
58        // PHP 8ではDom\DocumentクラスがDom\Nodeを継承し、C14NFileメソッドを提供します。
59        $dom = new DOMDocument();
60        // XML読み込み時に余分な空白を保持しない設定
61        $dom->preserveWhiteSpace = false; 
62        // 出力時にXMLを整形する設定(C14N出力そのものには影響しませんが、デバッグに便利です)
63        $dom->formatOutput = true;        
64
65        // 一時ファイルからXMLを読み込みます。
66        if (!$dom->load($inputTempFile)) {
67            echo "エラー: XMLコンテンツの読み込みに失敗しました。無効なXML形式かもしれません。\n";
68            return false;
69        }
70
71        // C14NFile メソッドを使用して、XML全体を正規化し、指定されたファイルに保存します。
72        // Dom\Notation クラスに直接このメソッドは存在しませんが、
73        // Dom\Document オブジェクトがXMLドキュメント全体のC14N処理を担います。
74        //
75        // 引数:
76        // 1. string $uri           : 正規化されたXMLを書き込むファイルパス
77        // 2. bool $exclusive       : 排他的C14Nを使用するかどうか(デフォルト: false)
78        // 3. bool $withComments    : コメントを含めるかどうか(デフォルト: false)
79        // 4. ?array $xpath         : 正規化するノードをXPathで指定(今回はXML全体なのでnull)
80        // 5. ?array $nsPrefixes    : 名前空間プレフィックスの配列(排他的C14Nの場合に利用)
81        $bytesWritten = $dom->C14NFile($outputFilePath, false, false);
82
83        if ($bytesWritten === false) {
84            echo "エラー: XMLのC14N正規化、またはファイルへの保存に失敗しました。\n";
85            return false;
86        }
87
88        echo "XMLコンテンツがCanonical XML (C14N) 形式で正規化され、\n";
89        echo "ファイル '{$outputFilePath}' に成功裏に保存されました。バイト数: {$bytesWritten}\n";
90        return true;
91
92    } catch (RuntimeException $e) {
93        echo "致命的なエラー: " . $e->getMessage() . "\n";
94        return false;
95    } finally {
96        // 処理の成功・失敗にかかわらず、作成した一時ファイルを削除します。
97        if ($inputTempFile && file_exists($inputTempFile)) {
98            unlink($inputTempFile);
99        }
100    }
101}
102
103// --------------------------------------------------------------------------
104// サンプルコード実行部分
105// --------------------------------------------------------------------------
106
107// 正規化するXMLコンテンツの例
108// DTDのNOTATION宣言を含めることで、Dom\Notationが扱うXMLの文脈を示します。
109$sampleXmlContent = <<<XML
110<?xml version="1.0" encoding="UTF-8"?>
111<!DOCTYPE document [
112    <!NOTATION gif SYSTEM "image/gif">
113    <!ENTITY icon SYSTEM "icon.gif" NDATA gif>
114]>
115<root attr="value" another-attr="another-value">
116    <!-- これはテスト用のコメントです -->
117    <item id="1">
118        <name>商品A</name>
119        <price>100</price>
120    </item>
121    <item id="2">
122        <name>商品B</name>
123        <price>200</price>
124    </item>
125    <element with="attributes" order="matters">
126        <sub-element/>
127    </element>
128</root>
129XML;
130
131// 正規化されたXMLを保存する出力ファイルパス
132$outputFilePath = __DIR__ . '/canonicalized_output.xml';
133
134// 関数を実行し、結果を表示します。
135if (canonicalizeAndSaveXml($sampleXmlContent, $outputFilePath)) {
136    echo "\n--- 正規化されたXMLのプレビュー ({$outputFilePath}) ---\n";
137    // 出力ファイルが存在することを確認してから読み込み
138    if (file_exists($outputFilePath)) {
139        echo file_get_contents($outputFilePath);
140    } else {
141        echo "エラー: 出力ファイルが見つかりません。\n";
142    }
143    echo "\n----------------------------------------------------\n";
144
145    // 注意: このスクリプトで生成された出力ファイルは、スクリプト完了後も残ります。
146    // 必要に応じて手動で削除してください(例: unlink($outputFilePath);)。
147} else {
148    echo "XML正規化処理が失敗しました。\n";
149}

C14NFileメソッドは、XMLドキュメントをCanonical XML(C14N)形式に正規化し、指定されたファイルに保存する機能を提供します。このメソッドはPHP 8において、通常DOMDocumentクラスで使用され、XMLドキュメント全体または特定のXMLノードを対象とします。リファレンス情報ではDom\Notationクラスに属するとされていますが、Dom\NotationはXMLのDTDの一部であり、DOMDocumentが扱うXMLドキュメント内部に含まれる可能性のある要素です。

サンプルコードでは、入力されたXMLコンテンツをDOMDocumentオブジェクトで読み込み、C14NFileメソッドを使ってXML全体を正規化して新しいファイルに保存します。これは、XMLの正規化された内容を新しいファイルに「コピー」する操作と見なせます。

引数としては、$uriに正規化されたXMLを書き込む出力ファイルパスを指定します。$exclusiveは排他的C14Nを使用するかどうか、$withCommentsはコメントを含めるかどうかを設定するオプションです。$xpath$nsPrefixesは、正規化の対象を絞り込む際に使用できます。このメソッドは、成功すると書き込まれたバイト数を示す整数を返し、失敗した場合はfalseを返します。これにより、異なるシステム間でXMLの一貫性を保ちやすくなります。

このサンプルコードでは、PHPのDOMDocumentクラスのC14NFileメソッドを使用しています。リファレンス情報にDom\Notationクラスのメソッドとありますが、実際にはDOMDocumentクラスのインスタンスに対して呼び出され、XMLドキュメント全体を正規化してファイルに保存します。このメソッドはXMLの内容を比較可能にするための標準化であり、単なるファイルコピーとは目的が異なります。メソッドの戻り値は成功時に書き込まれたバイト数、失敗時にfalseとなるため、必ずエラーチェックを行ってください。また、一時ファイルを使用する際は、処理の成功・失敗にかかわらず、finallyブロックなどで確実にファイルを削除し、残存させないよう注意が必要です。ファイルパスの指定には、書き込み権限のある場所を選んでください。

関連コンテンツ

関連IT用語

関連プログラミング言語