【PHP8.x】C14Nメソッドの使い方

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

作成日: 更新日:

基本的な使い方

C14Nメソッドは、DOMノードを正規化されたXML形式で出力するメソッドです。CharacterDataクラス(Text, Comment, CDATASectionなど)のノードに対して使用できます。C14NはCanonical XMLの略で、XML文書を特定の規則に従って標準化することで、内容が等価な文書を常に同じバイト列で表現できるようにします。これにより、XML文書の比較やデジタル署名の検証などが容易になります。

このメソッドは、ノード自身を含むサブツリー全体を正規化して出力します。出力形式は、W3C勧告のCanonical XML Version 1.0に準拠します。正規化処理では、属性の順序のソート、名前空間の明示的な宣言、不要な空白の削除などが行われます。

C14Nメソッドを使用することで、XML文書の構造や内容が同じであっても、属性の順序や空白の有無などによって異なるバイト列になってしまう問題を解決できます。システム間でXMLデータを交換する際や、XML文書を長期保存する際に、データの整合性を保つために非常に有効です。

引数として、排他的C14N、コメントの保持、プレフィックスリストなどを指定することで、より詳細な正規化処理を制御できます。これらの引数を適切に設定することで、特定の要件に合わせたXMLの正規化を行うことができます。C14Nメソッドは、XMLデータを扱う様々なシステムにおいて、データの標準化と整合性維持に貢献します。

構文(syntax)

1public Dom\CharacterData::C14N(string $exclusive = "", bool $withComments = true, ?array $nodes = null, ?string $namespacePrefix = null): bool

引数(parameters)

bool $exclusive = false, bool $with_comments = false, ?array $xpath = null, ?array $ns_prefixes = null

  • bool $exclusive = false: trueに設定すると、要素の属性のみを正規化します。
  • bool $with_comments = false: trueに設定すると、コメントノードも正規化対象に含めます。
  • ?array $xpath = null: 正規化するノードをXPathクエリで指定します。
  • ?array $ns_prefixes = null: 名前空間のプレフィックスを配列で指定します。

戻り値(return)

string|false

このメソッドは、指定されたキャラクターデータを正規化(CANONICALIZE)した結果を文字列として返します。正規化に失敗した場合は false を返します。

サンプルコード

PHP XML C14Nメソッドで正規化する

1<?php
2
3// DOMDocument を作成し、XML をロードします。
4$dom = new DOMDocument();
5$dom->loadXML('<root><child attribute="value">Text</child><!-- Comment --></root>');
6
7// CharacterData ノードを取得します(例:コメントノード)。
8$comment = $dom->documentElement->lastChild;
9
10// C14N を実行します。
11// exclusive, with_comments, xpath, ns_prefixes のデフォルト引数を使用します。
12$canonicalXml = $comment->C14N();
13
14// 結果を出力します。
15if ($canonicalXml !== false) {
16    echo $canonicalXml . "\n";
17} else {
18    echo "C14N failed.\n";
19}
20
21// exclusive モードで C14N を実行します。
22$canonicalXmlExclusive = $comment->C14N(true);
23
24// 結果を出力します。
25if ($canonicalXmlExclusive !== false) {
26    echo "Exclusive C14N: " . $canonicalXmlExclusive . "\n";
27} else {
28    echo "Exclusive C14N failed.\n";
29}
30?>

このサンプルコードは、PHPのDom\CharacterDataクラスのC14Nメソッドを使用して、XMLの正規化(Canonicalization)を行う方法を示しています。XMLの正規化とは、XMLドキュメントを標準的な形式に変換することです。

まず、DOMDocumentオブジェクトを作成し、XMLデータをロードします。次に、documentElementプロパティとlastChildプロパティを使用して、コメントノードを取得しています。C14Nメソッドは、このコメントノードに対してXML正規化を実行します。

C14Nメソッドの基本的な使い方は、$comment->C14N() のように引数なしで呼び出すことです。これにより、デフォルトの設定で正規化が行われます。引数には、以下のものがあります。

  • $exclusive: 排他的正規化を行うかどうかを指定するブール値。
  • $with_comments: コメントを含めるかどうかを指定するブール値。
  • $xpath: 正規化対象のノードをXPathで指定する配列。
  • $ns_prefixes: 名前空間プレフィックスの配列。

サンプルコードでは、最初に引数なしでC14Nメソッドを呼び出し、次に $exclusive = true を指定して排他的正規化を行っています。

C14Nメソッドは、正規化されたXML文字列を返します。失敗した場合はfalseを返します。サンプルコードでは、返り値がfalseでないことを確認し、正規化されたXML文字列を出力しています。C14N(true)とすることで、より厳格な排他的正規化を実行できます。これにより、より再現性の高いXMLデータを得ることができます。

Dom\CharacterData::C14N() は、XML の正規化を行うメソッドです。サンプルコードでは、コメントノードに対してC14Nを適用しています。引数$exclusivetrueにすると、排他的な正規化が行われます。xpathns_prefixesは、特定のノードや名前空間のみを正規化する場合に使用します。C14Nは、XMLの署名や比較を行う際に重要です。

このメソッドは、ノードの種類によっては期待通りの結果にならない場合があります。CharacterData 以外のノードに対して正規化を行いたい場合は、DOMDocument::C14N()の使用を検討してください。また、C14NはXML構造を変化させる可能性があるため、適用前にバックアップを取ることを推奨します。エラー処理として、戻り値が false の場合の処理を必ず記述しましょう。

PHP 8 XML C14N正規化する

1<?php
2
3// Dom\CharacterData::C14N メソッドのサンプルコード
4// XML ドキュメントを正規化 (Canonicalization) します。
5
6function canonicalize_xml_data(string $xml_string, bool $exclusive = false, bool $with_comments = false, ?array $xpath = null, ?array $ns_prefixes = null): string|false
7{
8    $dom = new DOMDocument();
9    $dom->loadXML($xml_string);
10
11    // CharacterData (Text ノードなど) を取得
12    $xpath_query = new DOMXPath($dom);
13    $text_nodes = $xpath_query->query('//text()');
14
15    if ($text_nodes === false || $text_nodes->length === 0) {
16        return false; // Text ノードが見つからない場合
17    }
18
19    $first_text_node = $text_nodes->item(0);
20
21    if ($first_text_node === null) {
22        return false; // ノードが null の場合
23    }
24
25    // C14N を実行
26    return $first_text_node->C14N($exclusive, $with_comments, $xpath, $ns_prefixes);
27}
28
29// XML 文字列の例
30$xml_string = '<root><child>Hello, World!</child><!-- comment --></root>';
31
32// C14N を実行 (コメントなし、排他的でない)
33$canonicalized_xml = canonicalize_xml_data($xml_string);
34
35if ($canonicalized_xml !== false) {
36    echo "Canonicalized XML: " . $canonicalized_xml . "\n";
37} else {
38    echo "Canonicalization failed.\n";
39}
40
41// C14N を実行 (コメントあり、排他的)
42$canonicalized_xml_with_comments = canonicalize_xml_data($xml_string, true, true);
43
44if ($canonicalized_xml_with_comments !== false) {
45    echo "Canonicalized XML (with comments, exclusive): " . $canonicalized_xml_with_comments . "\n";
46} else {
47    echo "Canonicalization failed.\n";
48}
49?>

このサンプルコードは、PHPのDom\CharacterDataクラスのC14Nメソッドを使用して、XMLドキュメントのテキストノードを正規化(Canonicalization)する方法を示します。XMLの正規化とは、XML文書を標準的な形式に変換することです。

canonicalize_xml_data関数は、XML文字列を受け取り、C14Nメソッドを呼び出して正規化されたXMLを返します。引数として、以下のものを指定できます。

  • $exclusive: 排他的な正規化を行うかどうかを指定するブール値。デフォルトはfalseです。
  • $with_comments: コメントを含めるかどうかを指定するブール値。デフォルトはfalseです。
  • $xpath: 正規化の対象となるノードを選択するためのXPath式を指定する配列。デフォルトはnullです。
  • $ns_prefixes: 名前空間プレフィックスを指定する配列。デフォルトはnullです。

関数はまず、与えられたXML文字列をDOMDocumentオブジェクトとしてロードします。次に、XPathを使用して、テキストノード(//text())を検索します。見つかった最初のテキストノードに対してC14Nメソッドを呼び出し、正規化されたXMLを文字列として返します。正規化に失敗した場合はfalseを返します。

サンプルコードでは、コメントなし、排他的でない正規化と、コメントあり、排他的な正規化の2つの例を示しています。C14Nメソッドは、XMLデータの整合性を保つために、デジタル署名などで利用されます。

Dom\CharacterData::C14Nメソッドは、XMLドキュメントの一部分(CharacterDataノード)を正規化する機能です。このメソッドは、XMLデータの構造や属性、名前空間などを一定の規則に従って変換し、異なる環境でも同じように解釈できるようにします。

引数の $exclusive は排他的な正規化を行うかどうか、$with_comments はコメントを含めるかどうかを指定します。$xpath$ns_prefixes は、正規化の範囲をXPathで指定したり、名前空間のプレフィックスを制限したりするために使用します。

サンプルコードでは、XPathで最初に現れるTextノードを取得し、そのノードに対してC14Nを実行しています。Textノードが見つからない場合はfalseを返します。C14Nメソッド自体も失敗時にfalseを返すため、戻り値のチェックは必ず行いましょう。XMLの構造によっては、期待どおりの結果が得られない可能性がある点に注意が必要です。

【PHP8.x】C14Nメソッドの使い方 | いっしー@Webエンジニア