Bagaimana cara mendapatkan innerHTML dari DOMNode?


96

Fungsi apa yang Anda gunakan untuk mendapatkan innerHTML dari DOMNode tertentu dalam implementasi PHP DOM? Bisakah seseorang memberikan solusi yang andal?

Tentu saja outerHTML juga bisa.

Jawaban:


152

Bandingkan varian yang diperbarui ini dengan Catatan Pengguna Manual PHP # 89718 :

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

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

    return $innerHTML; 
} 
?> 

Contoh:

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

Terima kasih. Ini bekerja dengan baik. Seharusnya $ dom-> preservWhiteSpace = false; sebelum dokumen dimuat?
Dawid Ohia

@ JohnM2: Ya, seharusnya .
hakre

Catatan tambahan: Sejak PHP 5.3.6 Anda dapat menyimpan sementara DOMDocument. Juga seseorang mungkin ingin mengganti trimdengan ltrim(atau bahkan menghapusnya sepenuhnya) untuk mempertahankan sedikit spasi seperti jeda baris.
hakre

Fungsi seperti ini harus ditambahkan ke kelas DomDocument.
Nate

3
Saya harus mengubah deklarasi fungsi untuk mengharapkan a DOMElementalih - alih a DOMNodesaat saya meneruskan pengembalian DOMDocument::getElementById(). Kalau-kalau itu membuat orang lain tersandung.
miken32

25

Berikut adalah versi dalam gaya pemrograman fungsional :

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

13

Untuk mengembalikan htmlelemen, Anda bisa menggunakan C14N () :

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

2
C14N akan mencoba untuk mengubah HTML menjadi XML yang valid. Misalnya <br> akan menjadi <br> </br>
ajaybc

Ini adalah cara kotor untuk membuang HTML elemen, tanpa harus menggunakan saveHTML yang akan mengeluarkan tag html, head dan body.
CONvid19

9

Versi sederhana dari jawaban Haim Evgi:

<?php

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

    $html = '';

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

    return $html;
}

Contoh penggunaan:

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

Tidak perlu mengatur preserveWhiteSpaceatau formatOutput.


4

Selain versi trincot yang bagus dengan array_mapdan implodetapi kali ini dengan array_reduce:

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

Masih belum mengerti, mengapa tidak ada reduce()metode yang menerima array dan iterator sama.


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

Berikut pendekatan lain berdasarkan komentar ini oleh Drupella di php.net, yang bekerja dengan baik untuk proyek saya. Ini mendefinisikan innerHTML()dengan membuat yang baruDOMDocument , mengimpor dan menambahkan ke node target, bukannya secara eksplisit melakukan iterasi pada node turunan.

InnerHTML

Mari kita definisikan fungsi pembantu ini:

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

di mana kita dapat menyertakan / mengecualikan tag target luar melalui argumen masukan kedua.

Contoh Penggunaan

Di sini kami mengekstrak HTML bagian dalam untuk tag target yang diberikan oleh atribut id "pertama":

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

Contoh langsung:

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


1

Kueri lama, tetapi ada metode bawaan untuk melakukannya. Cukup teruskan node target ke DomDocument->saveHtml().

Contoh lengkap:

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

Keluaran: <p>ciao questa è una <b>prova</b>.</p>


Peringatan: DOMDocument :: saveHTML () mengharapkan parameter 1 menjadi DOMNode, objek diberikan
Ivan Gusev
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.