Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Dom Objects in PHP, the default namespace is redeclared in some nodes

I'm working on a template engine, having migrated from regex driven to DOM driven. It appears though, that whenever I create a DomDocumentFragment to encapsulate some portion of a document temporarily, the namespace attribute is added to each node in the fragment. Since my default namespace for a given document will 99% of the time be XHTML, it's adding the XHTML namespace declaration.

Being the default namespace, this seems fruitless, and ultimately nodes in any other namespace will be stripped out at render time anyways.

Aside from iteratively removing namespace attributes, is there some way I can prevent this from occurring to begin with? Its quite problematic, as this will likely increase render time filesize considerably, as large portions of a given document may be stored in a fragment.

I've tried $doc->normalizeDocument(), but as I assumed, it did nothing.

like image 272
Dan Lugg Avatar asked Jan 26 '26 09:01

Dan Lugg


1 Answers

Depending on your tolerance for additional computation to solve what is mostly an aesthetic problem (I say mostly, since I agree it does take up extra space for nothing, but other than that is OK), you could run your entire XML through an XSL identity template.

I had to write a fully functional example to make sure the technique does indeed work:

<?php

$xmlIdentityTemplate = '<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>';

$xmlExample = '<?xml version="1.0"?>
<ns1:root xmlns:ns1="urn:ns1" xmlns:ns2="urn:ns2">
    <ns1:node1>
        <ns2:subnode1 xmlns:ns2="urn:ns2">node1 subnode1</ns2:subnode1>
        <ns2:subnode2 xmlns:ns2="urn:ns2">node1 subnode2</ns2:subnode2>
        <ns2:subnode3 xmlns:ns2="urn:ns2">node1 subnode3</ns2:subnode3>
        <ns2:subnode4 xmlns:ns2="urn:ns2">node1 subnode4</ns2:subnode4>
    </ns1:node1>
    <ns1:node2>
        <ns2:subnode1 xmlns:ns2="urn:ns2">node2 subnode1</ns2:subnode1>
        <ns2:subnode2 xmlns:ns2="urn:ns2">node2 subnode2</ns2:subnode2>
        <ns2:subnode3 xmlns:ns2="urn:ns2">node2 subnode3</ns2:subnode3>
        <ns2:subnode4 xmlns:ns2="urn:ns2">node2 subnode4</ns2:subnode4>
    </ns1:node2>
</ns1:root>';

$originalDocument = new DOMDocument();
$originalDocument->loadXML($xmlExample);

$xslDocument = new DOMDocument();
$xslDocument->loadXML($xmlIdentityTemplate);

$processor = new XSLTProcessor();
$processor->importStyleSheet($xslDocument);
$resultDocument = $processor->transformToDoc($originalDocument);

echo "<h1>Before:</h1>";
echo "<pre>" . htmlentities($originalDocument->saveXML()) . "</pre>";
echo "<h1>After:</h1>";
echo "<pre>" . htmlentities($resultDocument->saveXML()) . "</pre>";
like image 68
matb33 Avatar answered Jan 27 '26 23:01

matb33