CascadiaPHP 2024

DOMNode::C14N

(PHP 5 >= 5.2.0, PHP 7, PHP 8)

DOMNode::C14Nノードを文字列に正規化する

説明

public DOMNode::C14N(
    bool $exclusive = false,
    bool $withComments = false,
    ?array $xpath = null,
    ?array $nsPrefixes = null
): string|false

ノードを文字列に正規化します。

パラメータ

exclusive

指定した xpath あるいは名前空間プレフィックスにマッチするノードだけを対象としたパースを有効にする。

withComments

コメントを残して出力する。

xpath

ノードをフィルタする XPath の配列。 この配列のそれぞれのエントリは、以下の情報を持つ連想配列です:

  • XPath の式の文字列を含む query キー。必須です。
  • 名前空間のプレフィックス(keys) を名前空間URI (values) にマップした配列を含む namespaces キー。オプションです。

nsPrefixes

ノードを絞り込むための名前空間プレフィックスの配列。

戻り値

正規化したノードを文字列で返します。 失敗した場合に false を返します

例1 XPath クエリの例

以下のコードは、XPath クエリを使ってノードをフィルタし、 正規化する高度なやり方を示します。

<?php
$dom
= new DOMDocument();
$dom->loadXML(<<<XML
<root xmlns:food="urn:food">
<!-- redundant namespace declaration will be canonicalized -->
<food:fruit xmlns:food="urn:food">Apple</food:fruit>
<food:fruit>Orange</food:fruit>
<food:fruit>Pear</food:fruit>
<!-- vegetables here -->
<food:vegetable>Lettuce</food:vegetable>
</root>
XML);
echo
$dom->C14N(true, false, [
"query" => ".//f:fruit|.//f:fruit/text()",
"namespaces" => ["f" => "urn:food"],
]);
?>

上の例の出力は以下となります。

<food:fruit>Apple</food:fruit><food:fruit>Orange</food:fruit><food:fruit>Pear</food:fruit>

参考

add a note

User Contributed Notes 3 notes

up
21
Rijk
11 years ago
When working with (malformed) HTML, you're probably better off using DOMDocument's saveHTML() method instead. C14N() will attempt to make your HTML valid XML, for example by converting <br> to <br></br>.

So instead of:
$html = $Node->C14N();

Use:
$html = $Node->ownerDocument->saveHTML( $Node );
up
16
jorda at edpsciences dot org
9 years ago
C14N() returns an empty string if the node is not included in the document tree:
<?php
$d
= new DOMDocument('1.0');
$d->loadXML('<foo></foo>');
$n = $d->createElement('bar');
var_dump($n->C14N());
$d->documentElement->appendChild($n);
var_dump($n->C14N());
?>
output:
string(0) ""
string(11) "<bar></bar>"
up
3
lordbaco
8 years ago
[edit by nielsdos: This has been fixed starting in PHP 8.4]

Good to know:

<< Due to a known issue in XML canonicalization in PHP, processing large metadata files in SimpleSAMLphp takes a big amount of resources, with that amount growing approximately by the square of the number of entities in the metadata set >>
https://simplesamlphp.org/metaprocessing

<< The C14N() function appears to have a runtime that is O(N^2) (or possibly worse?) depending on input size, which means that it becomes very slow as the input grows. For example, an input with around 196000 nodes takes about 290 seconds, while an input with 486000 nodes takes 2200 seconds. >>
https://bugs.php.net/bug.php?id=53655

We had the same issue with a 4.1 MB XML (105k lines). The sample code of ticket #53655 takes 1h36 minute to canonicalize it!
To Top