在PHP中使用Dom Objects,在某些节​​点中重新声明默认命名空间

时间:2011-01-07 18:48:30

标签: php xml xhtml namespaces domdocument

我正在开发一个模板引擎,已经从正则表达式驱动迁移到DOM驱动。但是,无论何时我创建DomDocumentFragment来临时封装文档的某些部分,都会将命名空间属性添加到片段中的每个节点。由于给定文档的默认命名空间99%的时间都是XHTML,因此它添加了XHTML命名空间声明。

作为默认命名空间,这看起来毫无结果,并且最终在渲染时将剥离任何其他命名空间中的节点。

除了迭代删除命名空间属性之外,还有一些方法可以防止这种情况发生吗?这很成问题,因为这可能会大大增加渲染时间文件大小,因为给定文档的大部分可能存储在片段中。

我尝试过$doc->normalizeDocument(),但正如我所说,它没有做任何事情。

1 个答案:

答案 0 :(得分:2)

取决于您对额外计算的容忍度,以解决主要是美学问题(我说主要是,因为我同意它确实占用了额外的空间,但除此之外没关系),您可以通过XSL身份模板运行整个XML。

我必须编写一个功能齐全的示例来确保该技术确实有效:

<?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>";