【问题标题】:DOMElement replace HTML valueDOMElement 替换 HTML 值
【发布时间】:2016-10-24 04:18:56
【问题描述】:

我在 DOMElement 中有这个 HTML 字符串:

<h1>Home</h1>
test{{test}}

我想用一种方式替换这个内容,只有

<h1>Home</h1>
test

保留(所以我想删除{{test}})。

此时,我的代码如下所示:

$node->nodeValue = preg_replace(
    '/(?<replaceable>{{([a-z0-9_]+)}})/mi', '' , $node->nodeValue);

这不起作用,因为nodeValue 不包含节点的 HTML 值。 除了使用$node-&gt;C14N()之外,我无法弄清楚如何获取节点的HTML字符串,但是使用C14N我无法替换内容。 有什么想法可以在这样的 HTML 字符串中删除 {{test}} 吗?

【问题讨论】:

    标签: php dom preg-replace domdocument dom-node


    【解决方案1】:

    您尝试过DOMDocument::saveXML 功能吗? (http://php.net/manual/en/domdocument.savexml.php)

    它有第二个参数$node,您可以使用它指定打印 HTML/XML 的节点。

    所以,例如:

    <?php
    
    $doc = new DOMDocument('1.0');
    // we want a nice output
    $doc->formatOutput = true;
    
    $root = $doc->createElement('body');
    $root = $doc->appendChild($root);
    
    $title = $doc->createElement('h1', 'Home');
    $root->appendChild($title);
    
    $text = $doc->createTextNode('test{{test}}');
    $text = $root->appendChild($text);
    
    echo $doc->saveXML($root);
    
    ?>
    

    这会给你:

    <body>
      <h1>Home</h1>
      test{{test}}
    </body>
    

    如果你不想要&lt;body&gt; 标签,你可以循环遍历它的所有子节点:

    <?php
    
    foreach($root->childNodes as $child){    
        echo $doc->saveXML($child);
    }
    
    ?>
    

    这会给你:

    <h1>Home</h1>test{{test}}
    

    编辑:你当然可以用你已经在使用的正则表达式替换{{test}}

    <?php
    
    $xml = '';
    foreach($root->childNodes as $child){    
        $xml .= preg_replace(
                    '/(?<replaceable>{{([a-z0-9_]+)}})/mi', '', 
                    $doc->saveXML($child)
        );
    }
    
    ?>
    

    这会给你:

    <h1>Home</h1>test
    

    注意:我还没有测试过代码,但这应该会给你大致的想法。

    【讨论】:

      【解决方案2】:

      问题主要在于您如何浏览 DOM,但您的 RegExp 也存在问题; XPath 实际上在 DOM 操作方面提供了很大的灵活性,因此这是我的首选解决方案。

      假设你有一个这样构建的 DOMDocument(我附上了一个 XPath):

      $dom = new DOMDocument('1.0', 'utf-8');
      $xpath = new DOMXPath($dom);
      
      $node = $dom->createElement('div');
      $node->appendChild(
          $dom->createElement('h1', "Home")
          );
      $node->appendChild(
          $dom->createTextNode("test{{test}}")
          );
      
      $dom->appendChild($node);
      

      您可以在 XPath 中使用 '/div/text()' 专门针对该 &lt;div&gt; 的文本节点。

      所以要在该文本节点中替换 {{test}} 而不会破坏节点的其余部分,您可以这样做:

      $xpath->query('/div/text()')->item(0)->nodeValue = preg_replace(
              '/(.*){{[^}]+}}/m', 
              '$1',
              $xpath->query('/div/text()')->item(0)->nodeValue
      );
      

      有点复杂,但$dom-&gt;saveXML(); 的输出是:

      <?xml version="1.0" encoding="utf-8"?>
      <div><h1>Home</h1>test</div>
      

      {{test}} 已被删除,其余部分完好无损。

      【讨论】:

      • 我目前只有 DOMElement 节点可用,不能使用 dom 或 xpath。或者我也应该将孩子加载为 xpath。
      • 您可以将节点加载到一个带有“组成”root 节点的 DOMDocument 中 - 然后在您完成操作后提取原始元素。
      猜你喜欢
      • 2011-01-15
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      • 2011-09-02
      • 2011-01-07
      • 1970-01-01
      • 1970-01-01
      • 2021-06-12
      相关资源
      最近更新 更多