Quale funzione usi per ottenere innerHTML di un dato DOMNode nell'implementazione PHP DOM? Qualcuno può dare una soluzione affidabile?
Ovviamente lo farà anche outerHTML.
Quale funzione usi per ottenere innerHTML di un dato DOMNode nell'implementazione PHP DOM? Qualcuno può dare una soluzione affidabile?
Ovviamente lo farà anche outerHTML.
Risposte:
Confronta questa variante aggiornata con la nota utente del manuale PHP n. 89718 :
<?php
function DOMinnerHTML(DOMNode $element)
{
$innerHTML = "";
$children = $element->childNodes;
foreach ($children as $child)
{
$innerHTML .= $element->ownerDocument->saveHTML($child);
}
return $innerHTML;
}
?>
Esempio:
<?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);
}
?>
DOMDocument
. Inoltre si potrebbe voler sostituire il trim
con un ltrim
(o addirittura rimuoverlo completamente) per preservare un po 'di spazio bianco come le interruzioni di riga.
DOMElement
invece di a DOMNode
mentre stavo passando il ritorno da DOMDocument::getElementById()
. Nel caso in cui inciampi qualcun altro.
Per restituire il valore html
di un elemento, puoi usare C14N () :
$dom = new DOMDocument();
$dom->loadHtml($html);
$x = new DOMXpath($dom);
foreach($x->query('//table') as $table){
echo $table->C14N();
}
Una versione semplificata della risposta di Haim Evgi:
<?php
function innerHTML(\DOMElement $element)
{
$doc = $element->ownerDocument;
$html = '';
foreach ($element->childNodes as $node) {
$html .= $doc->saveHTML($node);
}
return $html;
}
Utilizzo di esempio:
<?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>
*/
Non è necessario impostare preserveWhiteSpace
o formatOutput
.
Oltre alla bella versione di trincot con array_map
e implode
ma questa volta con array_reduce
:
return array_reduce(
iterator_to_array($node->childNodes),
function ($carry, \DOMNode $child) {
return $carry.$child->ownerDocument->saveHTML($child);
}
);
Ancora non capisco, perché non esiste un reduce()
metodo che accetti array e iteratori allo stesso modo.
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);
}
}
Ecco un altro approccio basato su questo commento di Drupella su php.net, che ha funzionato bene per il mio progetto. Definisce il innerHTML()
creando un nuovoDOMDocument
, importando e aggiungendo ad esso il nodo di destinazione, invece di iterare esplicitamente sui nodi figli.
Definiamo questa funzione di supporto:
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 );
}
dove possiamo includere / escludere il tag di destinazione esterno tramite il secondo argomento di input.
Qui estraiamo l'HTML interno per un tag di destinazione dato dall'attributo id "first":
$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>
}
Esempio dal vivo:
http://sandbox.onlinephpfunctions.com/code/2714ea116aad9957c3c437d46134a1688e9133b8
Vecchia query, ma esiste un metodo integrato per farlo. Basta passare il nodo di destinazione a DomDocument->saveHtml()
.
Esempio completo:
$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);
Produzione: <p>ciao questa è una <b>prova</b>.</p>