Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
DOMNode::C14N() is way slower on created DOMDocuments than loaded ones
<?php
/**
* This code demonstrates the performance difference when calling
* DOMNode::C14N() on a generated DOMDocument versus on a DOMDocument that was
* loaded from a string.
*
* Calling DOMDocument::normalizeDocument() doesn't make any difference.
*
* Output example:
* Testing with 500 items
* Native DOM (not normalized)… 2.55357 seconds
* Native DOM (normalized)… 2.52199 seconds
* Export and re-import DOM… 0.06444 seconds
*/
define('NUMBER_OF_ITEMS', 500);
define('XML_NAME_SPACE', 'http://example.com/xml');
echo sprintf('Testing with %d items', NUMBER_OF_ITEMS) . PHP_EOL;
echo 'Generated DOM… ';
$nativeDOM = generate_random_dom();
$s = microtime(true);
iterate_with_xpath($nativeDOM);
echo number_format(microtime(true) - $s, 5) . ' seconds' . PHP_EOL;
echo 'Generated DOM with normalizeDocument()… ';
$nativeDOMNormalized = generate_random_dom();
$s = microtime(true);
$nativeDOMNormalized->normalizeDocument();
iterate_with_xpath($nativeDOMNormalized);
echo number_format(microtime(true) - $s, 5) . ' seconds' . PHP_EOL;
echo 'Export and re-import DOM… ';
$dom3 = generate_random_dom();
$s = microtime(true);
$importedXmlString = new \DOMDocument('1.0', 'UTF-8');
$importedXmlString->loadXML($dom3->saveXML());
iterate_with_xpath($importedXmlString);
echo number_format(microtime(true) - $s, 5) . ' seconds' . PHP_EOL;
/**
* Iterate over items' content and call C14N
*
* @param \DOMDocument $dom
*/
function iterate_with_xpath(\DOMDocument $dom): void
{
$xpath = new \DOMXPath($dom);
$xpath->registerNamespace('listElement', XML_NAME_SPACE);
/** @var \DOMElement $item */
foreach($xpath->query('//listElement:alpha', null, XML_NAME_SPACE) as $item) {
$item->C14N();
}
}
/**
* Generate random DOMDocument
*
* Example:
* <listElement>
* <listItem index="0">
* <alpha>random value here</alpha>
* </listItem>
* ...
* </listElement>
*
* @return \DOMDocument
*/
function generate_random_dom(): \DOMDocument
{
$dom = new \DOMDocument();
$dom->formatOutput = true;
/** @var \DOMElement $list */
$list = $dom->createElementNS(XML_NAME_SPACE, 'listElement');
$dom->appendChild($list);
for($i = 0; $i < NUMBER_OF_ITEMS; $i++) {
/** @var \DOMElement $listItem */
$listItem = $dom->createElementNS(XML_NAME_SPACE, 'listItem');
$listItem->setAttribute('index', $i);
$list->appendChild($listItem);
$subElement = $dom->createElementNS(XML_NAME_SPACE, 'alpha');
$subElement->appendChild($dom->createTextNode(uniqid('a', true)));
$listItem->appendChild($subElement);
}
return $dom;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment