Làm cách nào để nhận được InternalHTML của DOMNode?


96

Bạn sử dụng hàm nào để lấy innerHTML của một DOMNode nhất định trong triển khai DOM PHP? Ai đó có thể đưa ra giải pháp đáng tin cậy?

Tất nhiên, ngoàiHTML cũng sẽ làm được.

Câu trả lời:


152

So sánh biến thể cập nhật này với Ghi chú Người dùng Hướng dẫn sử dụng PHP # 89718 :

<?php 
function DOMinnerHTML(DOMNode $element) 
{ 
    $innerHTML = ""; 
    $children  = $element->childNodes;

    foreach ($children as $child) 
    { 
        $innerHTML .= $element->ownerDocument->saveHTML($child);
    }

    return $innerHTML; 
} 
?> 

Thí dụ:

<?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); 
} 
?> 

Cảm ơn. Nó hoạt động tốt. Không nên $ dom-> keepWhiteSpace = false; trước khi tải tài liệu?
Dawid Ohia

@ JohnM2: Đúng vậy .
hakre

Lưu ý bổ sung: Vì PHP 5.3.6, bạn có thể dự phòng tạm thời DOMDocument. Ngoài ra, người ta có thể muốn thay thế trimbằng một ltrim(hoặc thậm chí loại bỏ nó hoàn toàn) để bảo toàn một chút khoảng trắng như ngắt dòng.
hakre

Một chức năng như thế này sẽ được thêm vào lớp DomDocument.
Nate

3
Tôi đã phải thay đổi khai báo hàm để mong đợi một DOMElementthay vì a DOMNodekhi tôi chuyển trả về từ đó DOMDocument::getElementById(). Chỉ trong trường hợp nó đi người khác lên.
miken32

25

Đây là một phiên bản theo kiểu lập trình chức năng :

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

13

Để trả về htmlphần tử, bạn có thể sử dụng C14N () :

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

2
C14N sẽ cố gắng chuyển đổi HTML sang XML hợp lệ. Ví dụ: <br> sẽ trở thành <br> </br>
ajaybc

Đó là một cách bẩn để kết xuất HTML của phần tử, mà không cần phải sử dụng saveHTML sẽ xuất ra các thẻ html, head và body.
CONvid 19

9

Một phiên bản đơn giản của câu trả lời của Haim Evgi:

<?php

function innerHTML(\DOMElement $element)
{
    $doc = $element->ownerDocument;

    $html = '';

    foreach ($element->childNodes as $node) {
        $html .= $doc->saveHTML($node);
    }

    return $html;
}

Ví dụ sử dụng:

<?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>
*/

Không cần đặt preserveWhiteSpacehoặc formatOutput.


4

Ngoài phiên bản đẹp của trincot với array_mapimplodenhưng lần này với array_reduce:

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

Vẫn không hiểu, tại sao không có reduce()phương thức nào chấp nhận mảng và trình vòng lặp giống nhau.


3
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);
  }
}

2

Đây là một cách tiếp cận khác dựa trên nhận xét này của Drupella trên php.net, đã hoạt động tốt cho dự án của tôi. Nó xác định innerHTML()bằng cách tạo một DOMDocumentnút mới , nhập và thêm vào đó nút đích, thay vì lặp lại rõ ràng qua các nút con.

Bên trongHTML

Hãy xác định chức năng trợ giúp này:

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 );
}

nơi chúng tôi có thể bao gồm / loại trừ thẻ mục tiêu bên ngoài thông qua đối số đầu vào thứ hai.

Ví dụ sử dụng

Ở đây, chúng tôi trích xuất HTML bên trong cho thẻ mục tiêu được cung cấp bởi thuộc tính id "đầu tiên":

$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>
}

Ví dụ trực tiếp:

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


1

Truy vấn cũ, nhưng có một phương thức tích hợp để làm điều đó. Chỉ cần chuyển nút đích đến DomDocument->saveHtml().

Ví dụ đầy đủ:

$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);

Đầu ra: <p>ciao questa è una <b>prova</b>.</p>


Cảnh báo: DOMDocument :: saveHTML () mong muốn tham số 1 là DOMNode, đối tượng đã cho
Ivan Gusev
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.