【问题标题】:How to get innerHTML of DOMNode?如何获取DOMNode的innerHTML?
【发布时间】:2011-01-06 10:10:33
【问题描述】:

在 PHP DOM 实现中,您使用什么函数来获取给定 DOMNode 的 innerHTML?有人可以提供可靠的解决方案吗?

当然,outerHTML 也可以。

【问题讨论】:

    标签: php dom innerhtml


    【解决方案1】:

    Compare 这个更新的变体带有PHP Manual User Note #89718

    <?php 
    function DOMinnerHTML(DOMNode $element) 
    { 
        $innerHTML = ""; 
        $children  = $element->childNodes;
    
        foreach ($children as $child) 
        { 
            $innerHTML .= $element->ownerDocument->saveHTML($child);
        }
    
        return $innerHTML; 
    } 
    ?> 
    

    例子:

    <?php 
    $dom= new DOMDocument(); 
    $dom->preserveWhiteSpace = false;
    $dom->formatOutput       = true;
    $dom->load($html_string); 
    
    $domTables = $dom->getElementsByTagName("table"); 
    
    // Iterate over DOMNodeList (Implements Traversable)
    foreach ($domTables as $table) 
    { 
        echo DOMinnerHTML($table); 
    } 
    ?> 
    

    【讨论】:

    • 谢谢。它工作正常。不应该 $dom->preserveWhiteSpace = false;在文件加载之前?
    • @JohnM2: Yes it should.
    • 附加说明:从 PHP 5.3.6 开始,您可以省去临时的 DOMDocument。也有人可能想用ltrim 替换trim(甚至完全删除它)以保留一些空格,如换行符。
    • DomDocument 类应该添加这样的函数。
    • 我必须更改函数声明以期望 DOMElement 而不是 DOMNode,因为我正在传递来自 DOMDocument::getElementById() 的返回值。以防它绊倒别人。
    【解决方案2】:

    这是一个函数式编程风格的版本:

    function innerHTML($node) {
        return implode(array_map([$node->ownerDocument,"saveHTML"], 
                                 iterator_to_array($node->childNodes)));
    }
    

    【讨论】:

      【解决方案3】:

      要返回元素的html,可以使用C14N()

      $dom = new DOMDocument();
      $dom->loadHtml($html);
      $x = new DOMXpath($dom);
      foreach($x->query('//table') as $table){
          echo $table->C14N();
      }
      

      【讨论】:

      • C14N 将尝试将 HTML 转换为有效的 XML。例如
        将变为
      • 这是一种转储元素 HTML 的肮脏方式,无需使用将输出 html、head 和 body 标记的 saveHTML。
      【解决方案4】:

      Haim Evgi 回答的简化版本:

      <?php
      
      function innerHTML(\DOMElement $element)
      {
          $doc = $element->ownerDocument;
      
          $html = '';
      
          foreach ($element->childNodes as $node) {
              $html .= $doc->saveHTML($node);
          }
      
          return $html;
      }
      

      示例用法:

      <?php
      
      $doc = new \DOMDocument();
      $doc->loadHTML("<body><div id='foo'><p>This is <b>an <i>example</i></b> paragraph<br>\n\ncontaining newlines.</p><p>This is another paragraph.</p></div></body>");
      
      print innerHTML($doc->getElementById('foo'));
      
      /*
      <p>This is <b>an <i>example</i></b> paragraph<br>
      
      containing newlines.</p>
      <p>This is another paragraph.</p>
      */
      

      无需设置preserveWhiteSpaceformatOutput

      【讨论】:

        【解决方案5】:

        除了 trincot 的 array_mapimplode 的漂亮版本之外,这次是 array_reduce

        return array_reduce(
           iterator_to_array($node->childNodes),
           function ($carry, \DOMNode $child) {
                return $carry.$child->ownerDocument->saveHTML($child);
           }
        );
        

        还是不明白,为什么没有reduce() 方法可以接受数组和迭代器。

        【讨论】:

          【解决方案6】:
          function setnodevalue($doc, $node, $newvalue){
            while($node->childNodes->length> 0){
              $node->removeChild($node->firstChild);
            }
            $fragment= $doc->createDocumentFragment();
            $fragment->preserveWhiteSpace= false;
            if(!empty($newvalue)){
              $fragment->appendXML(trim($newvalue));
              $nod= $doc->importNode($fragment, true);
              $node->appendChild($nod);
            }
          }
          

          【讨论】:

            【解决方案7】:

            这里有另一种方法,基于 php.net 上 Drupella 的 this comment,它非常适合我的项目。它通过创建新的DOMDocument、导入并附加目标节点来定义innerHTML(),而不是显式迭代子节点。

            内部HTML

            让我们定义这个辅助函数:

            function innerHTML( \DOMNode $n, $include_target_tag = true ) {
              $doc = new \DOMDocument();
              $doc->appendChild( $doc->importNode( $n, true ) );
              $html = trim( $doc->saveHTML() );
              if ( $include_target_tag ) {
                  return $html;
              }
              return preg_replace( '@^<' . $n->nodeName .'[^>]*>|</'. $n->nodeName .'>$@', '', $html );
            }
            

            我们可以通过第二个输入参数包含/排除外部目标标签。

            使用示例

            这里我们提取由“first”id属性给出的目标标签的内部HTML:

            $html = '<div id="first"><h1>Hello</h1></div><div id="second"><p>World!</p></div>';
            $doc  = new \DOMDocument();
            $doc->loadHTML( $html );
            $node = $doc->getElementById( 'first' );
            
            if ( $node instanceof \DOMNode ) {
            
                echo innerHTML( $node, true );
                // Output: <div id="first"><h1>Hello</h1></div>    
            
                echo innerHTML( $node, false );
                // Output: <h1>Hello</h1>
            }
            

            活生生的例子:

            http://sandbox.onlinephpfunctions.com/code/2714ea116aad9957c3c437d46134a1688e9133b8

            【讨论】:

              【解决方案8】:

              旧查询,但有一个内置方法可以做到这一点。只需将目标节点传递给DomDocument-&gt;saveHtml()

              完整示例:

              $html = '<div><p>ciao questa è una <b>prova</b>.</p></div>';
              $dom = new DomDocument($html);
              @$dom->loadHTML($html);
              $xpath = new DOMXPath($dom);
              $node = $xpath->query('.//div/*'); // with * you get inner html without surrounding div tag; without * you get inner html with surrounding div tag
              $innerHtml = $dom->saveHtml($node);
              var_dump($innerHtml);
              

              输出:&lt;p&gt;ciao questa è una &lt;b&gt;prova&lt;/b&gt;.&lt;/p&gt;

              【讨论】:

              • 警告:DOMDocument::saveHTML() 期望参数 1 是 DOMNode,给定对象
              【解决方案9】:

              对于想要从 XPath 查询中获取 HTML 的人,这是我的版本:

              $xpath = new DOMXpath( $my_dom_object );
              
              $DOMNodeList = $xpath->query('//div[contains(@class, "some_custom_class_in_html")]');
              
              if( $DOMNodeList->count() > 0 ) {
                  $page_html = $my_dom_object->saveHTML( $DOMNodeList->item(0) );
              }
              

              【讨论】:

                猜你喜欢
                • 2010-11-02
                • 2016-03-22
                • 2018-03-31
                • 1970-01-01
                • 2015-12-10
                • 2014-06-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多