【PHP8.x】Dom\HTMLElement::C14NFile()メソッドの使い方
C14NFileメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
C14NFileメソッドは、HTMLElementオブジェクトが表すノードとその子孫ノードを正規化(C14N)し、その結果を指定されたファイルに保存する処理を実行するメソッドです。正規化とは、XML文書をW3Cが定める標準形式(Canonical XML)に変換するプロセスを指します。この処理により、属性の順序や空白文字の扱いなどが統一され、論理的に等価な文書は必ず同一のバイト列表現を持つようになります。この特性は、XMLデジタル署名などで文書の同一性を厳密に検証する際に不可欠です。このメソッドは、第一引数に出力先のファイルパスを文字列で指定する必要があります。さらに、オプションの引数を渡すことで、特定のノードセットのみを対象とする排他的正規化の実行、コメントノードの出力有無、XPath式による対象ノードの限定、名前空間プレフィックスの指定など、より詳細な正規化処理を制御することができます。処理が成功した場合はファイルに書き込まれたバイト数を整数で返し、失敗した場合は false を返します。
構文(syntax)
1$bytes_or_false = $htmlElement->C14NFile( 2 uri: 'path/to/output.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: 正規化するXMLドキュメントのURIを指定します。
- bool $exclusive = false: 排他ノードセットを使用するかどうかを指定します。
- bool $withComments = false: コメントを含めて正規化するかどうかを指定します。
- ?array $xpath = null: 正規化するノードをXPathで指定します。
- ?array $nsPrefixes = null: 名前空間のプレフィックスをマッピングする連想配列を指定します。
戻り値(return)
int|false
このメソッドは、XML要素の正規化処理が成功した場合は1を、失敗した場合はfalseを返します。
サンプルコード
PHP Dom\HTMLElement::C14NFileでHTMLを正規化する
1<?php 2 3/** 4 * 指定されたHTMLコンテンツから<body>要素を抽出し、 5 * その要素をCanonical XML (C14N) 形式でファイルに保存します。 6 * 7 * この関数は、Dom\HTMLElement クラスに所属する C14NFile メソッドの利用例を示します。 8 * C14N (Canonical XML) は、XMLドキュメントの内容を一貫した形式(正規化)に変換する国際標準です。 9 * XMLドキュメントの内容の同一性を保証する際に用いられ、主にXML署名などのセキュリティ関連で重要となります。 10 * 11 * @param string $htmlContent 正規化したいHTML文字列。 12 * @param string $outputFilePath 正規化されたXMLを保存するファイルのパス。 13 * @return bool ファイルの保存が成功した場合は true、失敗した場合は false。 14 */ 15function saveHtmlBodyAsC14NFile(string $htmlContent, string $outputFilePath): bool 16{ 17 // 1. DOMDocument オブジェクトを作成し、HTMLコンテンツをロードします。 18 // @ はHTMLパース時の警告を抑制するために使用しています。 19 $dom = new DOMDocument(); 20 @$dom->loadHTML($htmlContent); 21 22 // 2. 正規化の対象となる Dom\HTMLElement (ここでは <body> 要素) を取得します。 23 // getElementsByTagName は DOMNodeList を返します。 24 $bodyElements = $dom->getElementsByTagName('body'); 25 26 // <body>要素が見つからない場合はエラーとします。 27 if ($bodyElements->length === 0) { 28 echo "エラー: HTMLコンテンツに <body> 要素が見つかりませんでした。\n"; 29 return false; 30 } 31 32 // 最初の <body> 要素を取得します。 33 // この要素は Dom\HTMLElement が表すHTML要素の一つであり、C14NFile メソッドを呼び出すことができます。 34 $targetElement = $bodyElements->item(0); 35 36 // 3. C14NFile メソッドを呼び出して、要素を正規化しファイルに保存します。 37 // 引数: 38 // - $uri: 正規化されたXMLを書き込むファイルのパス。 39 // - $exclusive: 排他的正規化 (Exclusive C14N) を使用するか (bool, デフォルトは false)。 40 // ここでは一般的な正規化のため false を指定。 41 // - $withComments: コメントを正規化された出力に含めるか (bool, デフォルトは false)。 42 // ここではコメントを含めるため true を指定。 43 // - $xpath, $nsPrefixes: 正規化の対象を細かく指定するためのオプション(ここではデフォルトのまま)。 44 $bytesWritten = $targetElement->C14NFile( 45 $outputFilePath, 46 false, // $exclusive (排他的正規化ではない) 47 true // $withComments (コメントを含める) 48 ); 49 50 // 戻り値が false の場合、書き込みに失敗しています。 51 if ($bytesWritten === false) { 52 echo "エラー: C14Nファイル '$outputFilePath' の書き込みに失敗しました。\n"; 53 return false; 54 } 55 56 echo "C14N形式のXMLが '$outputFilePath' に正常に書き込まれました。書き込みバイト数: $bytesWritten バイト\n"; 57 return true; 58} 59 60// --- サンプルコードの実行 --- 61 62// 正規化したいHTMLコンテンツの例 63$sampleHtmlContent = <<<HTML 64<!DOCTYPE html> 65<html> 66<head> 67 <meta charset="utf-8"> 68 <title>C14N サンプル</title> 69</head> 70<body> 71 <div id="main-content"> 72 <h1>PHP C14NFile メソッドの例</h1> 73 <p>これは正規化されるテキストの一部です。</p> 74 <!-- このコメントも正規化された出力に含まれます --> 75 <p class="note" > 属性や空白も正規化されます。 </p> 76 </div> 77 <div> 78 <span id="footer">フッター情報</span> 79 </div> 80</body> 81</html> 82HTML; 83 84// 出力ファイル名 85$outputFile = 'canonical_output.xml'; 86 87// 関数を呼び出してC14Nファイルを作成 88if (saveHtmlBodyAsC14NFile($sampleHtmlContent, $outputFile)) { 89 // 成功した場合、生成されたファイルの内容を表示 90 echo "\n--- 生成されたファイルの内容 ---\n"; 91 echo file_get_contents($outputFile); 92 echo "\n--------------------------------\n"; 93 94 // ファイルを削除(テスト後不要であればコメントを解除) 95 // unlink($outputFile); 96} else { 97 echo "C14Nファイルの生成に失敗しました。\n"; 98} 99
PHPのDom\HTMLElement::C14NFileメソッドは、HTMLやXMLドキュメントの特定の要素をCanonical XML(C14N)形式でファイルに保存する機能を提供します。C14Nは、XMLドキュメントの内容を一貫した形式に正規化する国際標準であり、XML署名などセキュリティ関連でドキュメントの同一性を保証する際に重要な役割を果たします。
このサンプルコードは、指定されたHTMLコンテンツから<body>要素を抽出し、その内容をC14N形式でファイルに保存する例です。まずDOMDocumentにHTMLをロードし、getElementsByTagNameで<body>要素を取得します。取得した<body>要素はDom\HTMLElementオブジェクトとして扱われ、そのC14NFileメソッドを呼び出します。第一引数$uriには正規化されたXMLの保存先ファイルパスを指定します。第二引数$exclusiveは排他的正規化の有無を、第三引数$withCommentsはコメントを含めるかを制御します。その他の引数は、正規化の対象を細かく指定する際に利用できます。
メソッドは、ファイルへの書き込みが成功した場合は書き込まれたバイト数をint型で返し、失敗した場合はfalseを返します。この機能により、要素の内容を確実に比較可能な形式で永続化することが可能になります。
このサンプルコードでは、@演算子でHTMLパース時の警告を抑制していますが、通常、@によるエラー抑制は避け、適切なエラー処理を実装するようにしましょう。C14NFileメソッドはXMLの内容の同一性を保証する正規化を目的とし、XML署名などのセキュリティ用途で特に重要です。単なるXML整形とは異なる点に留意してください。C14NFileは直接ファイルに書き込むため、指定パスへの書き込み権限が必要です。また、同名ファイルは上書きされますので注意しましょう。メソッドは書き込みに失敗するとfalseを返すため、必ず戻り値をチェックし、エラーハンドリングを行うようにしましょう。引数のexclusiveやwithCommentsは正規化の挙動に影響を与えますので、目的に合わせて適切に設定してください。
PHP Dom::C14NFileでXMLを正規化しファイル保存する
1<?php 2 3/** 4 * Dom\HTMLElement::C14NFile メソッドのサンプルコード 5 * 6 * このメソッドは、DOM要素をXML正規化 (Canonicalization) し、その結果を指定されたファイルに書き出します。 7 * キーワード "php cp" との関連性としては、「正規化されたXMLの内容を新しいファイルに保存(コピー)する」 8 * という形で解釈し、そのファイル生成処理を示します。 9 * 10 * PHP 8 の新しい Dom 拡張を使用します。 11 */ 12 13/** 14 * 指定されたDom\HTMLElement要素をXML正規化し、その結果を指定のファイルに保存します。 15 * 16 * @param string $outputFilePath 正規化されたXMLを保存するファイルパス。 17 * @return void 18 */ 19function demonstrateC14NFile(string $outputFilePath): void 20{ 21 // 1. 新しい Dom\Document を作成します。 22 // Dom\Document はXMLやHTMLドキュメント全体を表現するオブジェクトです。 23 $document = new Dom\Document('1.0', 'UTF-8'); 24 $document->formatOutput = true; // 出力を整形して読みやすくします。 25 26 // 2. ルート要素を作成し、ドキュメントに追加します。 27 // Dom\HTMLElement は Dom\Element を継承しており、通常は Dom\Document::createElement() で作成されます。 28 // ここではHTMLの 'body' 要素を例にしますが、XMLの任意の要素に適用可能です。 29 $bodyElement = $document->createElement('body'); 30 $document->appendChild($bodyElement); 31 32 // 3. 子要素 'p' を作成し、属性とテキストコンテンツを追加します。 33 // この $paragraphElement は Dom\Element のインスタンスであり、Dom\HTMLElement のメソッドを呼び出すことができます。 34 $paragraphElement = $document->createElement('p', 'これは正規化されるテキストです。'); 35 $paragraphElement->setAttribute('id', 'intro'); 36 $bodyElement->appendChild($paragraphElement); 37 38 // 4. コメント要素を追加します。C14NFile の引数でコメントを含めるか制御できます。 39 $commentElement = $document->createComment('これは正規化時に含めることができるコメントです'); 40 $bodyElement->appendChild($commentElement); 41 42 echo "--- 元のDOMツリーの内容(一部抜粋) ---\n"; 43 echo $document->saveXML($bodyElement) . "\n\n"; // body要素以下を出力 44 45 // 5. Dom\HTMLElement (ここでは $paragraphElement) の C14NFile メソッドを呼び出します。 46 // このメソッドは、指定された要素の正規化されたXML表現をファイルに書き出します。 47 // 48 // 引数: 49 // $uri: 正規化された内容を保存するファイルのパス。 50 // $exclusive: 排他的正規化を使用するかどうか (true/false)。falseで非排他的正規化。 51 // $withComments: コメントを含めるかどうか (true/false)。trueにするとコメントも正規化結果に含まれます。 52 // $xpath: 特定のノードセットのみを正規化する場合にXPath式の配列を指定 (省略可能)。 53 // $nsPrefixes: 名前空間のプレフィックスを制限する場合に指定 (省略可能)。 54 echo "要素を正規化し、ファイルに保存しています: {$outputFilePath}\n"; 55 $bytesWritten = $bodyElement->C14NFile( 56 $outputFilePath, 57 false, // $exclusive: false (非排他的正規化を使用) 58 true // $withComments: true (コメントも正規化結果に含める) 59 ); 60 61 // 6. 戻り値を確認し、処理結果を表示します。 62 // 成功した場合は書き込まれたバイト数を、失敗した場合は false を返します。 63 if ($bytesWritten === false) { 64 echo "エラー: ファイルへの正規化されたXMLの書き込みに失敗しました。\n"; 65 } else { 66 echo "成功: " . $bytesWritten . " バイトが '{$outputFilePath}' に書き込まれました。\n"; 67 echo "ファイル '{$outputFilePath}' の内容を確認してください。\n"; 68 } 69 70 // 注意: このサンプルコードでは、生成されたファイルを自動的に削除しません。 71 // 実行後に内容を確認し、手動で削除してください。 72} 73 74// サンプルコードを実行するファイルパスを指定します。 75$outputFile = __DIR__ . '/normalized_output.xml'; 76 77// 関数を呼び出して実行します。 78demonstrateC14NFile($outputFile); 79 80?>
「Dom\HTMLElement::C14NFile」メソッドは、PHP 8から利用できる新しいDom拡張に属し、XMLドキュメント内の特定の要素(Dom\HTMLElement)をXML正規化(Canonicalization)し、その結果を指定されたファイルに保存する機能を提供します。XML正規化とは、XML文書の異なる表現を標準化し、一意のバイト列として出力する処理のことです。
サンプルコードでは、まずDom\Documentオブジェクトを作成し、HTMLのbody要素やp要素、コメントなどを含むDOMツリーを構築しています。その後、$bodyElementというDom\HTMLElementインスタンスに対してC14NFileメソッドを呼び出し、その要素とその子孫を正規化しています。
このメソッドの第一引数$uriには、正規化されたXMLデータが書き込まれるファイルのパスを指定します。第二引数$exclusiveは排他的正規化を行うかどうかを真偽値で設定し、第三引数$withCommentsは正規化結果にXMLコメントを含めるかどうかを真偽値で指定します。サンプルでは、非排他的正規化でコメントを含めるように設定しています。メソッドが正常に処理を完了すると、ファイルに書き込まれたバイト数を整数で返します。もしファイルへの書き込みに失敗した場合はfalseを返します。キーワード「php cp」が示すように、正規化されたXMLの内容を新しいファイルに「コピー」して生成する際に活用でき、特定のDOM要素から標準化されたXMLファイルを効率的に作成することが可能です。
Dom\HTMLElement::C14NFileメソッドは、指定したDOM要素をXML正規化し、その結果を指定のファイルに保存します。これは、正規化されたXMLの内容を新しいファイルとして生成する操作と理解できます。PHP 8の新しいDom拡張が利用されているため、実行環境でこの拡張が有効になっているかを確認してください。第一引数で指定する出力ファイルパスには、書き込み権限が必要です。メソッドの戻り値は成功時に書き込まれたバイト数、失敗時にfalseが返りますので、処理の成否を=== falseで厳密に確認し、適切にエラー処理を行ってください。$withComments引数でコメントを含めるかを制御できます。また、サンプルコードで作成されたファイルは自動で削除されませんので、確認後は手動で削除してください。