DOMNode'un innerHTML'si nasıl elde edilir?


98

PHP DOM uygulamasında belirli bir DOMNode'un innerHTML'sini almak için hangi işlevi kullanıyorsunuz? Birisi güvenilir çözüm verebilir mi?

Tabii ki externalHTML de işe yarar.

Yanıtlar:


153

Karşılaştırma ile bu güncellenmiş varyantını PHP Manual Kullanıcı Not # 89718 :

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

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

    return $innerHTML; 
} 
?> 

Misal:

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

Teşekkürler. İyi çalışıyor. $ Dom-> preserveWhiteSpace = false olmamalıdır; belge yüklemeden önce mi?
Dawid Ohia

@ JohnM2: Evet olmalı .
hakre

Ek notlar: PHP 5.3.6'dan beri geçici olanı yedekleyebilirsiniz DOMDocument. Ayrıca bir değiştirmek isteyebilirsiniz trimbir ile ltrimsatır aralıklarında gibi boşluk biraz korumak için (hatta tamamen kaldırmak).
hakre

DomDocument sınıfına böyle bir işlev eklenmelidir.
Nate

3
Dönüşü geçerken a DOMElementyerine a beklemek için işlev bildirimini değiştirmek zorunda kaldım . Başkasının tuzağına düşmesi ihtimaline karşı. DOMNodeDOMDocument::getElementById()
miken32

26

İşte işlevsel programlama stilindeki bir sürüm :

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

14

htmlBir elemanın döndürülmesi için C14N () kullanabilirsiniz :

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

2
C14N, HTML'yi geçerli bir XML'e dönüştürmeyi deneyecektir. Örneğin <br>, <br> </br>
ajaybc

Html, head ve body etiketlerinin çıktısını alacak saveHTML'yi kullanmak zorunda kalmadan öğenin HTML'sini dökmenin kirli bir yolu.
Pedro Lobito

9

Haim Evgi'nin cevabının basitleştirilmiş bir versiyonu:

<?php

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

    $html = '';

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

    return $html;
}

Örnek kullanım:

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

preserveWhiteSpaceVeya ayarlamanıza gerek yok formatOutput.


4

Trincot'un güzel versiyonuna ek olarak array_mapve ile implodeama bu sefer array_reduce:

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

Yine de anlamıyorum, neden reduce()dizileri ve yineleyicileri kabul eden bir yöntem olmadığını .


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

İşte Drupella'nın php.net'teki bu yorumuna dayanan ve projem için iyi sonuç veren başka bir yaklaşım . Alt düğümler üzerinde açıkça yinelemek yerine, innerHTML()yeni bir oluşturarak DOMDocument, içe aktararak ve ona hedef düğümü ekleyerek tanımlar .

InnerHTML

Bu yardımcı işlevi tanımlayalım:

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

burada dış hedef etiketi ikinci giriş argümanı aracılığıyla dahil edebilir / hariç tutabiliriz.

Kullanım Örneği

Burada, "ilk" id özelliği tarafından verilen bir hedef etiket için iç HTML'yi çıkarıyoruz:

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

Canlı örnek:

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


1

Eski sorgu, ancak bunu yapmak için yerleşik bir yöntem var. Sadece hedef düğümü iletin DomDocument->saveHtml().

Tam örnek:

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

Çıktı: <p>ciao questa è una <b>prova</b>.</p>


Uyarı: DOMDocument :: saveHTML () parametre 1'in DOMNode olmasını bekliyor, nesne verildi
Ivan Gusev
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.