未捕获的异常'DOMException',消息'Not Found Error'

时间:2011-03-12 17:23:57

标签: domdocument php

基本上我正在为我的CMS编写一个模板系统,我想要一个模块化的结构,让人们输入标签,如:

<module name="news" /><include name="anotherTemplateFile" />然后我想在我的php中找到并替换为动态HTML。

有人在这里向我指出了DOMDocument,但我已经遇到了一个问题。

我正在尝试在模板中找到所有<include />标签,并用一些简单的html替换它们。这是我的模板代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>CMS</title>
<include name="head" />
</head>

<body>

<include name="header" />

<include name="content" />

<include name="footer" />

</body>
</html>

这是我的PHP:

$template = new DOMDocument();
$template->load("template/template.tpl");

foreach( $template->getElementsByTagName("include") as $include ) {
    $element = '<input type="text" value="'.print_r($include, true).'" />';
    $output = $template->createTextNode($element);
    $template->replaceChild($output, $include);
}

echo $template->saveHTML();

现在,我收到了致命错误Uncaught exception 'DOMException' with message 'Not Found Error'

我看了这个,似乎是因为我的<include />标签不一定是$template的直接孩子而不是替换它们。

如何独立于血统替换它们?

谢谢

汤姆

修改

基本上我有各种各样的脑波。如果我为我的PHP做了类似的事情,我会看到它试图做我想做的事情:

$template = new DOMDocument();
    $template->load("template/template.tpl");

    foreach( $template->getElementsByTagName("include") as $include ) {
        $element = '<input type="text" value="'.print_r($include, true).'" />';
        $output = $template->createTextNode($element);
        // this line is different:
        $include->parentNode->replaceChild($output, $include);
    }

    echo $template->saveHTML();

然而,只有在我的HTML的<body>中才会发生1次更改...当我有3:/ /

2 个答案:

答案 0 :(得分:3)

这是DOMDocument-&gt;加载的问题,请尝试

$template->loadHTMLFile("template/template.tpl"); 

但你可能需要给它一个.html扩展名。

这是在寻找一个html或xml文件。此外,无论何时使用带有html的DOMDocument,最好在加载调用之前使用libxml_use_internal_errors(true);

好的,这个工作:

foreach( $template->getElementsByTagName("include") as $include ) {
     if ($include->hasAttributes()) {
     $includes[] = $include;
     }
     //var_dump($includes);
 }
 foreach ($includes as $include) {
            $include_name = $include->getAttribute("name");
        $input = $template->createElement('input');
$type = $template->createAttribute('type');
$typeval = $template->createTextNode('text');
$type->appendChild($typeval);
$input->appendChild($type);
$name = $template->createAttribute('name');
$nameval = $template->createTextNode('the_name');
$name->appendChild($nameval);
$input->appendChild($name);
$value = $template->createAttribute('value');
$valueval = $template->createTextNode($include_name);
$value->appendChild($valueval);
$input->appendChild($value);
if ($include->getAttribute("name") == "head") {
       $template->getElementsByTagName('head')->item(0)->replaceChild($input,$include);
}
else {
        $template->getElementsByTagName("body")->item(0)->replaceChild($input,$include);
}
        }
        //$template->load($nht);
        echo $template->saveHTML();

答案 1 :(得分:1)

  

然而,它似乎只改变了我的HTML中的1个出现...当我有3.:/

DOM节点列表是“实时”:当您从文档中删除<include>元素(通过替换它)时,它会从列表中消失。相反,如果您在文档中添加新的<include>,它将显示在您的列表中。

对于来自元素childNodes的NodeList,您可能会期望这样,但返回的getElementsByTagName的NodeLists也是如此。它是W3C DOM标准的一部分,发生在Web浏览器的DOM以及PHP的DOMDocument中。

所以你在这里有一个破坏性的迭代。删除第一个<include>(列表中的项目0),第二个<include>(之前的项目1)成为新项目0.现在,当您转到列表中的下一个项目时,项目1是过去是第2项,导致你只看一半的项目。

PHP的foreach循环看起来可能会保护你,但实际上它的覆盖范围与传统的索引for循环完全相同。

我会尽量避免为PHP创建一个新的模板语言;已经有这么多了,更不用说PHP本身了。用DOMDocument创建一个也会特别慢。

eta:一般来说,正则表达式替换会更快,假设一个简单的匹配模式不会引入回溯负载。但是,如果您坚持使用XML语法,那么正则表达式在解析它时并不是很好。但是你想做什么,用PHP已经不能做了?

<?php function write_header() { ?>
    <p>This is the header bit!</p>
<? } ?>

<body>
    ...
    <?php write_header(); ?>
    ...
</body>