domdocument — Как вставить HTML в текстовый узел с DOMNode в переполнении стека

У меня есть сценарий PHP, который использует DOMDocument и DOMXPath, чтобы найти и заменить коды слияния в шаблоне HTML. Простой пример может быть:

<html>
<head>
<title>Title</title>
</head>
<body>
<p>Hello {greeting}!</p>
<table><tr>
<td>Details:</td>
<td>{details}</td>
</tr></table>
</body>
</html>

Следующий код заменяет поля на основе ассоциативного массива, где ключ соответствует полю слияния:

private function substituteFields (DOMNode $node, $fields)
{
$x = new DOMXPath ($node->ownerDocument);
foreach ($fields as $field => $value)
{
$query = $x->query (".//text()[contains(., '{" . $field . "}')]", $node);

foreach ($query as $subnode)
{
$subnode->nodeValue = str_replace ("{" . $field . "}", $value, $subnode->nodeValue);
}
}
}

Это работает хорошо.

Однако для некоторых кодов слияния в них должен быть подставлен HTML:

$fields ['greeting'] = "Joe Soap";
$fields ['details'] = "<div class='details'>Details here</div>";

Подстановка происходит, но HTML избегается, что, вероятно, является разумной идеей в большинстве случаев.

Могу ли я обойти это?

0

Решение

Я обошелся с этим немного неуклюже, но пока это работает. Если есть лучшие решения, я с радостью изменю свой ответ!

По сути, это ищет открывающий тег<«символ в тексте подстановки. Если он находит его, он вызывает метод подстановки HTML, который я изменил из этого вопрос, ответ и комментарии.

У него есть ограничение в том, что он не может заменить середину HTML-узла. Например, следующее не будет работать:

<p>Here is a bit of {html_code}</p>

Но это можно сделать так:

<p>Here is a bit of <span>{html_code}</span></p>

Вот модифицированный код:

private function substituteFields (DOMNode $node, $fields)
{
$x = new DOMXPath ($node->ownerDocument);
foreach ($fields as $field => $value)
{
$query = $x->query (".//text()[contains(., '{" . $field . "}')]", $node);

foreach ($query as $subnode)
{
$replace = str_replace ("{" . $field . "}", $value, $subnode->nodeValue);

if (substr ($replace, 0, 1) != "<")
{
$subnode->nodeValue = $replace;
}
else
{
$this->appendHTML ($subnode, $replace);
}
}
}
}

private function appendHTML (DOMNode $parent, $source)
{
$tmpDoc = new DOMDocument();
$tmpDoc->loadHTML ($source);
foreach ($tmpDoc->getElementsByTagName ('body')->item (0)->childNodes as $node)
{
$importedNode = $parent->ownerDocument->importNode ($node, true);
$parent->parentNode->replaceChild ($importedNode, $parent);
}
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector