Wie bekomme ich innerHTML von DOMNode?


95

Welche Funktion verwenden Sie, um innerHTML eines bestimmten DOMNode in der PHP-DOM-Implementierung abzurufen? Kann jemand eine zuverlässige Lösung geben?

Natürlich reicht OuterHTML auch.

Antworten:


151

Vergleichen Sie diese aktualisierte Variante mit dem 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; 
} 
?> 

Beispiel:

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

Vielen Dank. Es funktioniert gut. Sollte nicht $ dom-> bewahrenWhiteSpace = false; vor dem Laden des Dokuments sein?
Dawid Ohia

@ JohnM2: Ja sollte es .
hakre

Zusätzliche Hinweise: Seit PHP 5.3.6 können Sie die temporäre ersparen DOMDocument. Möglicherweise möchten Sie auch das trimdurch ein ersetzen ltrim(oder es sogar vollständig entfernen), um ein wenig Leerzeichen wie Zeilenumbrüche zu erhalten.
hakre

Eine solche Funktion sollte der DomDocument-Klasse hinzugefügt werden.
Nate

3
Ich musste die Funktionsdeklaration ändern, um a DOMElementanstelle von a zu erwarten, DOMNodeda ich die Rückgabe von übergeben habe DOMDocument::getElementById(). Nur für den Fall, dass es jemand anderen auslöst.
miken32

25

Hier ist eine Version in einem funktionalen Programmierstil :

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

13

Um das htmleines Elements zurückzugeben, können Sie C14N () verwenden :

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

2
C14N versucht, den HTML-Code in ein gültiges XML zu konvertieren. Zum Beispiel wird <br> <br> <
br

Es ist eine schmutzige Methode, den HTML-Code des Elements zu sichern, ohne saveHTML verwenden zu müssen, das HTML-, Kopf- und Body-Tags ausgibt.
CONvid19

9

Eine vereinfachte Version von Haim Evgis Antwort:

<?php

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

    $html = '';

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

    return $html;
}

Anwendungsbeispiel:

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

Es besteht keine Notwendigkeit zu setzen preserveWhiteSpaceoder formatOutput.


4

Zusätzlich zu Trincots netter Version mit array_mapund implodediesmal aber mit array_reduce:

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

Ich verstehe immer noch nicht, warum es keine reduce()Methode gibt, die Arrays und Iteratoren gleichermaßen akzeptiert.


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

Hier ist ein weiterer Ansatz, der auf diesem Kommentar von Drupella auf php.net basiert und für mein Projekt gut funktioniert hat. Es definiert das, innerHTML()indem ein neuer DOMDocumentZielknoten erstellt, importiert und an diesen angehängt wird, anstatt explizit über untergeordnete Knoten zu iterieren.

InnerHTML

Definieren wir diese Hilfsfunktion:

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

Hier können wir das äußere Ziel-Tag über das zweite Eingabeargument ein- / ausschließen.

Anwendungsbeispiel

Hier extrahieren wir den inneren HTML-Code für ein Ziel-Tag, das durch das "erste" ID-Attribut angegeben wird:

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

Live-Beispiel:

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


1

Alte Abfrage, aber es gibt eine eingebaute Methode, um das zu tun. Übergeben Sie einfach den Zielknoten an DomDocument->saveHtml().

Vollständiges Beispiel:

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

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


Warnung: DOMDocument :: saveHTML () erwartet, dass Parameter 1 DOMNode ist, Objekt angegeben
Ivan Gusev
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.