0

我有一个 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 正在被转义,这在大多数情况下可能是一个明智的想法。

我可以解决这个问题吗?

4

1 回答 1

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);
    }
}
于 2017-02-12T13:33:25.873 回答