如何在PHP中使用DOMNode将HTML插入到文本节点中

时间:2017-02-11 12:53:40

标签: php domdocument domxpath dom-node

我有一个PHP脚本,它使用DOMDocument和DOMXPath来查找和替换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);
        }
    }
}

以下代码根据键与匹配字段匹配的关联数组替换字段:

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

这很好用。

但是,某些合并代码需要将HTML替换为:

@NgModule({
  imports: [HttpModule],
  providers: []
})
export class MyModule {
  static forRoot(config: MyConfiguration): ModuleWithProviders {
    return {
      ngModule: MyModule,
      providers: [
        SomeService,
        {
          provide: SomeOtherService,
          useFactory: (some: SomeService, http: Http) => {
            switch (config.type) {
              case 'cloud':
                return new SomeOtherService(new SomethingSpecificForCloud());
              case 'server':
                return new SomeOtherService(new SomethingSpecificForServer());
            }
          },
          deps: [SomeService, Http]
        },

      ]
    };
  }
}

替换正在发生,但HTML正在被转义,这在大多数情况下可能是一个明智的想法。

我可以解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

我有点笨拙地绕过这个,但它现在有效。如果有更好的解决方案,我很乐意修改我的答案!

基本上,这会查找开头标记“&lt;”替换文本中的字符。如果找到一个,它会调用我从此question, answer and comments修改的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);
    }
}