Uncaught исключение «DOMException» с сообщением «Not Found Error» - PullRequest
3 голосов
/ 12 марта 2011

В сущности, я пишу систему шаблонов для своей 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, они не заменяют их.

Как я могу заменить их независимо от спуска?

Спасибо

Tom

EDIT

В основном у меня была своего рода мозговая волна. Если я делаю что-то подобное для своего 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();

Тем не менее, кажется, что только 1 изменится в <body> моего HTML ... когда у меня 3.: /

Ответы [ 2 ]

3 голосов
/ 12 марта 2011

Это проблема с вашим DOMDocument-> load, попробуйте

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

Но вам может потребоваться дать ему расширение .html.

это ищет html илиXML-файл.Кроме того, всякий раз, когда вы используете DOMDocument с html, рекомендуется использовать libxml_use_internal_errors(true); перед вызовом загрузки.

OKAY THIS WORKS:

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 голос
/ 12 марта 2011

Однако, кажется, только 1 изменится в моем HTML ... когда у меня 3.: /

DOM NodeLists являются «живыми»: когда вы удаляете элемент <include> из документа (заменяя его), он исчезает из списка. И наоборот, если вы добавите новый <include> в документ, он появится в вашем списке.

Вы могли бы ожидать это для NodeList, который приходит из элемента childNodes, но то же самое верно для NodeList, которые возвращаются getElementsByTagName. Он является частью стандарта W3C DOM и встречается в DOM веб-браузеров, а также в DOMDocument PHP.

Итак, у вас есть деструктивная итерация. Удалите первый <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>
...