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

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

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

作成日: 更新日:

基本的な使い方

C14Nメソッドは、DOMTextオブジェクトが表すテキストノードを、W3C勧告の仕様に基づいて正規化(正準化)し、その結果を文字列として取得するために実行するメソッドです。正規化とは、XML文書の論理的な意味を変えずに、空白の扱い、文字参照の展開、属性の順序といった物理的な表現を、定められた一貫性のある形式に変換する処理のことです。これにより、見た目上の記述が異なるXML文書でも、意味的に等価であれば全く同じ文字列を生成できます。この特性は、XMLデジタル署名などで文書の同一性を厳密に検証する際に不可欠となります。引数を用いることで、コメントノードを含めるかどうかの指定や、排他的正規化(Exclusive XML Canonicalization)の適用など、正規化のルールを細かく制御することが可能です。メソッドの実行に成功すると正規化されたノードの文字列を返しますが、処理に失敗した場合は false を返します。

構文(syntax)

1<?php
2
3// DOMDocumentオブジェクトを作成します
4$document = new DOMDocument();
5
6// XML文字列を読み込みます
7$document->loadXML('<root>Some sample text</root>');
8
9// テキストノードを取得します (<root>タグ内のテキスト部分)
10$textNode = $document->documentElement->firstChild;
11
12// DOMTextオブジェクトに対してC14N()メソッドを呼び出し、
13// 正規化された文字列を取得します。
14$canonicalizedString = $textNode->C14N();
15
16// 結果を出力します
17echo $canonicalizedString;
18
19?>

引数(parameters)

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

  • bool $exclusive = false: trueを指定すると、このノードの最小の排他的なコンテキストで正規化された出力を生成します。
  • bool $withComments = false: trueを指定すると、コメントノードも正規化に含めます。
  • ?array $xpath = null: 正規化から除外するXPath式を指定する配列。
  • ?array $nsPrefixes = null: 正規化から除外する名前空間プレフィックスを指定する配列。

戻り値(return)

string|false

C14N メソッドは、指定されたノードとその子孫を正規化し、その結果を文字列として返します。正規化に失敗した場合は false を返します。

サンプルコード

PHP DOMText C14N でテキスト正規化する

1<?php
2
3/**
4 * DOMText::C14N メソッドの使用例を示します。
5 * このメソッドは、DOMTextノードのコンテンツをXML正規化アルゴリズムに従って表現します。
6 * テキストノードの場合、通常は元のテキストとほとんど変わらないか、
7 * 改行コードの統一といった微細な調整にとどまります。
8 *
9 * @return void
10 */
11function demonstrateDomTextC14N(): void
12{
13    // 1. DOMDocumentインスタンスを作成します。
14    // XMLを整形して読み込むため、preserveWhiteSpaceとformatOutputを設定します。
15    $doc = new DOMDocument();
16    $doc->preserveWhiteSpace = false; // テキストノード以外の空白を無視(構造整形のため)
17    $doc->formatOutput = true;        // 整形出力
18
19    // 2. サンプルXML文字列を定義します。
20    // <item>要素内のテキストノードを対象にします。
21    $xmlString = <<<XML
22<root>
23    <item id="1">
24        This is some text.
25        <!-- This is a comment inside item 1 -->
26        <subitem>More text inside.</subitem>
27    </item>
28    <item id="2">
29        Another piece of text.
30    </item>
31</root>
32XML;
33
34    // 3. XMLをDOMDocumentにロードします。
35    if (!$doc->loadXML($xmlString)) {
36        echo "エラー: XMLのロードに失敗しました。\n";
37        return;
38    }
39
40    // 4. DOMXPathを使用して、特定のテキストノードを探します。
41    // ここでは、最初の<item>要素の直下にあるテキストノードを取得します。
42    // XPathではテキストノードを 'text()' で指定します。
43    $xpath = new DOMXPath($doc);
44    $nodes = $xpath->query('/root/item[@id="1"]/text()');
45
46    if ($nodes === false || $nodes->length === 0) {
47        echo "エラー: 指定されたXPathでテキストノードが見つかりませんでした。\n";
48        return;
49    }
50
51    // 5. 見つかった最初のノードがDOMTextのインスタンスであることを確認します。
52    $textNode = $nodes->item(0);
53
54    if ($textNode instanceof DOMText) {
55        echo "見つかったDOMTextノードの現在の値: '" . $textNode->nodeValue . "'\n\n";
56
57        // 6. DOMText::C14N() メソッドを呼び出し、正規化された文字列を取得します。
58        // 引数なし(デフォルト)で呼び出します。
59        // ($exclusive = false, $withComments = false)
60        $canonicalizedText = $textNode->C14N();
61
62        if ($canonicalizedText !== false) {
63            echo "--- C14Nの結果 (デフォルト引数) ---\n";
64            echo "'" . $canonicalizedText . "'\n\n";
65        } else {
66            echo "エラー: テキストノードの正規化に失敗しました。\n\n";
67        }
68
69        // コメントを含めるオプション (withComments = true) を試みます。
70        // ただし、DOMTextノード自体はコメントを直接子として持たないため、
71        // この引数はDOMText::C14Nにおいては通常、出力に影響を与えません。
72        $canonicalizedTextWithComments = $textNode->C14N(false, true);
73
74        if ($canonicalizedTextWithComments !== false) {
75            echo "--- C14Nの結果 (withComments = true) ---\n";
76            echo "'" . $canonicalizedTextWithComments . "'\n\n";
77            echo "注: DOMTextノードの場合、'withComments' 引数は通常、出力に変化をもたらしません。\n";
78            echo "コメントはテキストノードの兄弟要素として存在することが一般的です。\n\n";
79        } else {
80            echo "エラー: コメントを含めたテキストノードの正規化に失敗しました。\n\n";
81        }
82
83        // DOMText::C14Nの他の引数 ($xpath, $nsPrefixes) は、
84        // 通常、DOMDocumentやDOMElement全体を正規化する際に使用されることが多く、
85        // 特定のDOMTextノードの文脈ではあまり一般的ではありません。
86    } else {
87        echo "エラー: 見つかったノードはDOMTextインスタンスではありませんでした。\n";
88    }
89}
90
91// 関数を実行します。
92demonstrateDomTextC14N();

このサンプルコードは、PHPのDOM拡張機能が提供するDOMText::C14N()メソッドの使用方法を示しています。このメソッドは、XMLのテキストコンテンツを標準的な形式に正規化する役割を持ちます。テキストノードに適用した場合、通常は元のテキストとほとんど変わらないか、改行コードの統一といった微細な調整が行われます。

コードではまず、DOMDocumentインスタンスを作成し、提供されたXML文字列をロードします。次に、DOMXPathを使用して最初の<item>要素内にあるテキストノードを特定し、取得しています。

取得したDOMTextノードに対してC14N()メソッドを呼び出すと、そのテキストがXML正規化アルゴリズムに従って処理された文字列が返されます。デフォルトでは、コメントは含まれません。引数にtrueを設定してコメントを含めるオプションを試していますが、DOMTextノード自体はコメントを直接の子として持たないため、通常、その出力に変化はありません。

引数$exclusiveは排他的正規化を行うかどうか、$withCommentsはコメントを含めるかどうかを決定します。$xpath$nsPrefixesは、より複雑な正規化のスコープを指定するために使用されますが、DOMTextノード単体の正規化ではあまり使用されません。メソッドは正規化された文字列を返しますが、失敗した場合はfalseを返します。

DOMText::C14Nは、テキストノードをXML正規化しますが、通常、元のテキストから大きな変化はありません。主に改行コードの統一など微細な調整にとどまります。メソッドの戻り値は、成功時に正規化された文字列、失敗時にfalseですので、必ずエラーチェックを行ってください。引数の$withCommentsは、DOMTextノード単体では通常出力に影響しません。コメントはテキストノードの兄弟要素として扱われるためです。この引数は、DOMDocumentDOMElement全体の正規化で意味を持ちます。$xpath$nsPrefixes引数も、同様にDOMTextノード単体での使用は稀です。XML操作では、DOMXPathで目的のノードを正確に取得し、instanceofでノードの型を確認する習慣をつけると、より安全にコードを記述できます。

PHP: DOMText::C14N でXMLテキスト正規化する

1<?php
2
3/**
4 * DOMText::C14N() メソッドを使用してXMLテキストノードを正規化するサンプル関数です。
5 *
6 * この関数は、XMLドキュメント内の特定のテキストノードをDOMText::C14N()メソッドで正規化する例を示します。
7 * キーワード「c14n11」に関連して、PHPのリファレンスが `$exclusive = true` の場合に
8 * Canonical XML 1.1(またはExclusive Canonical XML 1.0)を指すと記述しているため、
9 * その設定での正規化を中心にデモンストレーションを行います。
10 *
11 * DOMText::C14N()は、テキストノード自体の正規化文字列を返します。
12 * テキストノード単体では、名前空間宣言、属性の順序、コメントの処理といった
13 * C14Nの複雑な正規化ルールが適用される対象がないため、
14 * 基本的にはノードのテキスト内容 (nodeValue) がそのまま返されることがほとんどです。
15 * C14Nの主な目的はXML文書のバイト列表現を一意にすることで、
16 * その真価は通常、DOMDocumentまたはDOMElement全体に適用されたときに発揮されます。
17 */
18function demonstrateDomTextC14N(): void
19{
20    // サンプルXML文字列を定義します。
21    // 名前空間と、テキストノードに隣接するコメントを含めます。
22    $xmlString = <<<XML
23<root xmlns:ex="http://example.com/ns">
24    <element>Hello, XML!</element>
25    <data>
26        <item>
27            これはテキストノードの内容です。<!-- これはコメントです -->
28        </item>
29    </data>
30</root>
31XML;
32
33    // DOMDocumentオブジェクトを作成し、XMLをロードします。
34    $dom = new DOMDocument();
35    $dom->loadXML($xmlString);
36
37    // XPathを使って特定のテキストノードを探します。
38    // <item>要素の直接の子であるテキストノードを取得します。
39    // このXML構造では、"            これはテキストノードの内容です。" の部分が取得されます。
40    // (前後の改行と空白文字もテキストノードの一部とみなされます)。
41    $xpath = new DOMXPath($dom);
42    $textNodes = $xpath->query('//item/text()');
43
44    if ($textNodes->length === 0) {
45        echo "指定されたテキストノードが見つかりませんでした。\n";
46        return;
47    }
48
49    // 最初に見つかったテキストノードを対象とします。
50    // ここで取得されるのは "            これはテキストノードの内容です。" のDOMTextノードです。
51    /** @var DOMText $textNode */
52    $textNode = $textNodes->item(0);
53
54    echo "--- DOMText::C14N() のデモンストレーション ---\n\n";
55
56    echo "対象のテキストノードの生のテキスト内容 (nodeValue):\n";
57    echo "'" . $textNode->nodeValue . "'\n\n";
58
59    // DOMText::C14N() メソッドを呼び出します。
60    // 引数:
61    // $exclusive = true: PHPドキュメントの記述に基づき、Canonical XML 1.1 (またはExclusive Canonical XML 1.0) に準拠します。
62    // $withComments = false: コメントを含めないで正規化します。
63    // `$xpath` と `$nsPrefixes` 引数はテキストノードのC14Nでは通常効果がないため、ここでは使用しません。
64    $c14nStringExclusive = $textNode->C14N(true, false);
65
66    echo "C14N (exclusive=true, withComments=false) による正規化結果:\n";
67    if ($c14nStringExclusive !== false) {
68        echo "'" . $c14nStringExclusive . "'\n\n";
69    } else {
70        echo "正規化に失敗しました。\n\n";
71    }
72
73    // 比較のために、$exclusive = false で実行してみます。
74    // DOMTextノードのC14Nでは、$exclusive の設定は結果にほとんど影響を与えません。
75    $c14nStringNonExclusive = $textNode->C14N(false, false);
76
77    echo "C14N (exclusive=false, withComments=false) による正規化結果:\n";
78    if ($c14nStringNonExclusive !== false) {
79        echo "'" . $c14nStringNonExclusive . "'\n\n";
80    } else {
81        echo "正規化に失敗しました。\n\n";
82    }
83
84    // $withComments = true にして実行してみます。
85    // テキストノードに直接コメントノードは含まれないため、この設定もDOMText::C14N()の結果には影響を与えません。
86    // コメントはテキストノードの「兄弟」ノードであるため、そのテキストノードのC14Nには含まれません。
87    $c14nStringWithComments = $textNode->C14N(false, true);
88
89    echo "C14N (exclusive=false, withComments=true) による正規化結果:\n";
90    if ($c14nStringWithComments !== false) {
91        echo "'" . $c14nStringWithComments . "'\n\n";
92    } else {
93        echo "正規化に失敗しました。\n\n";
94    }
95
96    echo "--- 補足 ---\n";
97    echo "ご覧の通り、DOMText::C14N() の結果は、通常はノードのテキスト内容 ('nodeValue') と同じになります。\n";
98    echo "これは、テキストノード単体では、名前空間宣言や属性の順序付け、他のノード(コメントなど)の有無といった\n";
99    echo "C14Nの複雑なルールが適用される対象がないためです。\n";
100    echo "XML文書全体の正規化を行う場合は、通常 DOMDocument::C14N() または DOMElement::C14N() を使用します。\n";
101}
102
103// 関数を実行してデモンストレーションを開始します。
104demonstrateDomTextC14N();
105

PHP 8のDOMText::C14N()メソッドは、XMLドキュメント内のテキストノードを正規化するための機能です。C14N(Canonical XML)とは、XML文書のバイト列表現を一意にするための標準であり、異なるシステム間でXMLの内容が同一であることを保証する際に利用されます。

このメソッドは、指定されたテキストノードの内容を正規化された文字列として返します。引数$exclusivetrueに設定すると、キーワード「c14n11」に関連するCanonical XML 1.1(または排他的Canonical XML 1.0)のルールに基づいた正規化を試みます。$withCommentsは、コメントを含めるかどうかを制御する引数ですが、テキストノードそのものには直接コメントは含まれないため、この設定が結果に影響することは稀です。残りの引数$xpath$nsPrefixesは、通常、テキストノードのC14Nでは利用されません。

しかし、DOMText::C14N()メソッドが対象とするのは単一のテキストノードであるため、名前空間宣言のプレフィックス、属性の順序付け、他のノードとの関連性といったC14Nの複雑なルールが適用される要素がありません。このため、メソッドの実行結果は、通常、テキストノードの元の内容(nodeValue)がそのまま返されることがほとんどです。メソッドが成功した場合は正規化された文字列が、失敗した場合はfalseが戻り値となります。XML文書全体の正規化を行う場合は、通常DOMDocument::C14N()メソッドなどを使用します。

DOMText::C14N()はXMLのテキストノードを正規化しますが、通常はそのテキスト内容(nodeValue)がそのまま返されます。これは、テキストノード単体では名前空間や属性、コメントなど、C14Nの複雑なルールが適用される対象がないためです。サンプルコードのように$exclusive$withCommentsといった引数を指定しても、テキストノードレベルでは正規化結果にほとんど影響を与えない点にご注意ください。XML文書全体や特定の要素を正規化したい場合は、通常DOMDocument::C14N()DOMElement::C14N()を使用します。また、このメソッドは失敗した場合にfalseを返す可能性があるため、常に結果をチェックし、適切なエラーハンドリングを行うようにしてください。キーワードのc14n11$exclusive = trueで関連しますが、テキストノード単体ではその違いは明確に現れません。

関連コンテンツ

関連プログラミング言語