2010-05-06 13 views
10

Come modificare innerHTML di una dump di php?Cambia innerHTML di un php DOMElement

+0

Non è possibile, direttamente. Dovrai avere una funzione di intermediario per prendere una stringa e trasformarla in una serie di DOMElement. Potresti scrivere tu stesso, anche se sono sicuro che qualcosa del genere esiste sul web. –

+0

Non esiste una proprietà innerHTML nella classe DOMElement php. Prova a guardare qui: http://php.net/manual/en/class.domelement.php e qui: http://www.php.net/manual/en/class.domtext.php – Babiker

risposta

0

Date un'occhiata a questa libreria PHP semplice HTML DOM Parser http://simplehtmldom.sourceforge.net/

Sembra piuttosto semplice. Puoi modificare la proprietà innertext dei tuoi elementi. Potrebbe aiutare.

+1

PHP, non JavaScript .. L'implementazione di PHP di DOM non ha una proprietà 'innerHTML'. –

+1

sì, colpa mia. ma php5 HTML DOM parser ha 'innertext'. http://simplehtmldom.sourceforge.net/ – Jull

+0

Questa non è la libreria a cui l'OP si riferiva. Vedi: http://php.net/manual/en/book.dom.php Ma potresti modificare la tua risposta e il link alla libreria che hai trovato e vedere se l'OP vuole cambiare. –

1

Penso che la cosa migliore che puoi fare sia trovare una funzione che porterà il DOMElement a cui vuoi cambiare il InnerHTML, copiarlo e sostituirlo.

In PHP molto approssimativa:

function replaceElement($el, $newInnerHTML) { 
    $newElement = $myDomDocument->createElement($el->nodeName, $newInnerHTML); 
    $el->parentNode->insertBefore($newElement, $el); 
    $el->parentNode->removeChild($el); 

    return $newElement; 
} 

Questo non si tiene conto gli attributi e le strutture nidificate, ma penso che questo ti porterà sulla strada giusta.

+2

Per chiunque altro provi questo codice - Ho dovuto usare $ el-> parentNode-> insertBefore invece di $ el-> insertBefore. – whichdan

+0

Questo funziona per l'impostazione innerText not innerHTML. Il secondo parametro di createElement non accetta la formattazione HTML. – Greg

+0

concordato, @greg. Questo codificherà i caratteri in HTML. – Kafoso

7

avevo bisogno di fare questo per un progetto di recente e si è conclusa con una proroga per DOMElement: http://www.keyvan.net/2010/07/javascript-like-innerhtml-access-in-php/

Ecco un esempio che mostra come viene utilizzato:

<?php 
require_once 'JSLikeHTMLElement.php'; 
$doc = new DOMDocument(); 
$doc->registerNodeClass('DOMElement', 'JSLikeHTMLElement'); 
$doc->loadHTML('<div><p>Para 1</p><p>Para 2</p></div>'); 
$elem = $doc->getElementsByTagName('div')->item(0); 

// print innerHTML 
echo $elem->innerHTML; // prints '<p>Para 1</p><p>Para 2</p>' 

// set innerHTML 
$elem->innerHTML = '<a href="http://fivefilters.org">FF</a>'; 

// print document (with our changes) 
echo $doc->saveXML(); 
?> 
0

Ecco una sostituzione per funzione classe I ha appena scritto:

Sostituirà l'innerHtml di una classe. Puoi anche specificare il tipo di nodo es. div/p/a ecc

function replaceInnerHtmlByClass($html, $replace=null, $class=null, $nodeType=null){ 
    if(!$nodeType){ $nodeType = '*'; } 
    $dom = new DOMDocument(); 
    $dom->loadHTML($html); 
    $xpath = new DOMXPath($dom); 
    $nodes = $xpath->query("//{$nodeType}[contains(concat(' ', normalize-space(@class), ' '), '$class')]"); 
    foreach($nodes as $node) { 
    while($node->childNodes->length){ 
     $node->removeChild($node->firstChild); 
    } 
    $fragment = $dom->createDocumentFragment(); 
    $fragment->appendXML($replace); 
    $node->appendChild($fragment); 
    } 
    return $dom->saveHTML($dom->documentElement); 
} 

Ecco un'altra funzione che ho scritto per rimuovere i nodi con una classe specifica, ma conservando l'HTML interno.

L'impostazione di sostituzione su true eliminerà l'html interno.

L'impostazione di sostituzione su qualsiasi altro contenuto sostituirà l'html interno con il contenuto fornito.

funzioni
function stripTagsByClass($html, $class=null, $nodeType=null, $replace=false){ 
    if(!$nodeType){ $nodeType = '*'; } 
    $dom = new DOMDocument(); 
    $dom->loadHTML($html); 
    $xpath = new DOMXPath($dom); 
    $nodes = $xpath->query("//{$nodeType}[contains(concat(' ', normalize-space(@class), ' '), '$class')]"); 
    foreach($nodes as $node) { 
    $innerHTML = ''; 
    $children = $node->childNodes; 
    foreach($children as $child) { 
     $tmp = new DOMDocument(); 
     $tmp->appendChild($tmp->importNode($child,true));  
     $innerHTML .= $tmp->saveHTML(); 
    } 
    $fragment = $dom->createDocumentFragment(); 
    if($replace !== null && $replace !== false){ 
     if($replace === true){ $replace = ''; } 
     $innerHTML = $replace; 
    } 
    $fragment->appendXML($innerHTML); 
    $node->parentNode->replaceChild($fragment, $node); 
    } 
    return $dom->saveHTML($dom->documentElement); 
} 

Tesi può essere facilmente adattato per utilizzare altri attributi come selettore.

Mi serviva solo per valutare l'attributo di classe.

1

Sembra che appendXML non funzioni sempre, ad esempio se si tenta di aggiungere XML con 3 livelli.Qui è la funzione che ho scritto che da sempre lavora (che si desidera impostare $ contenuto come innerHTML a $ element):

function setInnerHTML($DOM, $element, $content) { 
    $DOMInnerHTML = new DOMDocument(); 
    $DOMInnerHTML->loadHTML($content); 
    $contentNode = $DOMInnerHTML->getElementsByTagName('body')->item(0)->firstChild; 
    $contentNode = $DOM->importNode($contentNode, true); 
    $element->appendChild($contentNode); 
    return $elementNode; 
} 
+1

La variabile '$ elementNode' restituita non è definita - non dovrebbe essere' $ contentNode'? Si potrebbe semplificare la funzione usando '$ element-> ownerDocument' invece di dover passare in' $ DOM'. Questo importa solo il primo figlio di qualunque contenuto $ contenga. Per importare l'intero frammento, rimuovere '-> firstChild 'alla riga 4. –

-1

Ecco come si fa:

$doc = new DOMDocument(''); 
$label = $doc->createElement('label'); 

$label->appendChild($doc->createTextNode('test')); 
$li->appendChild($label); 

echo $doc->saveHTML(); 
0

Sviluppare su dalla risposta di Joanna Goch , questa funzione inserirà un nodo di testo o un frammento HTML:

function nodeFromContent($node, $content) { 
    //creates a text node, or dom node if content contains html 
    $lt = strpos($content, '<'); 
    $gt = strrpos($content, '>'); 
    if (!($lt === false || $gt === false) && $gt > $lt) { 
     //< followed by > means potentially contains HTML 
     $DOMInnerHTML = new DOMDocument(); 
     $DOMInnerHTML->loadHTML($content); 
     $contentNode = $DOMInnerHTML->getElementsByTagName('body')->item(0); 
     $newNode = $node->ownerDocument->importNode($contentNode, true); 
    } else { 
     $newNode = $node->ownerDocument->createTextNode($content); 
    } 
    return $newNode; 
} 

utilizzo

$newNode = nodeFromContent($node, $content); 
$node->parentNode->insertBefore($newNode, $node); 
//or $node->appendChild($newNode) depending on what you require 
0
function setInnerHTML($DOM, $element, $innerHTML) { 
    $node = $DOM->createTextNode($innerHTML); 
    $element->appendChild($node); 
} 
2

Un'altra soluzione:

1) creare nuovi DOMDocumentFragment dalla stringa HTML da inserire; 2) rimuove il vecchio contenuto del nostro elemento eliminando i suoi nodi figli; 3) aggiungi DOMDocumentFragment al nostro elemento.

function setInnerHTML($element, $html) 
{ 
    $fragment = $element->ownerDocument->createDocumentFragment(); 
    $fragment->appendXML($html); 
    while ($element->hasChildNodes()) 
     $element->removeChild($element->firstChild); 
    $element->appendChild($fragment); 
} 

In alternativa, possiamo sostituire il nostro elemento con la sua clean copy e quindi aggiungere DOMDocumentFragment a questo clone.

function setInnerHTML($element, $html) 
{ 
    $fragment = $element->ownerDocument->createDocumentFragment(); 
    $fragment->appendXML($html); 
    $clone = $element->cloneNode(); // Get element copy without children 
    $clone->appendChild($fragment); 
    $element->parentNode->replaceChild($clone, $element); 
} 

prova:

$doc = new DOMDocument(); 
$doc->loadXML('<div><span style="color: green">Old HTML</span></div>'); 
$div = $doc->getElementsByTagName('div')->item(0); 
echo $doc->saveHTML(); 

setInnerHTML($div, '<p style="color: red">New HTML</p>'); 
echo $doc->saveHTML(); 

// Output: 
// <div><span style="color: green">Old HTML</span></div> 
// <div><p style="color: red">New HTML</p></div> 
+0

Sebbene questo snippet di codice possa risolvere la domanda, [inclusa una spiegazione] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro, e queste persone potrebbero non conoscere le ragioni del tuo suggerimento sul codice. Cerca anche di non affollare il tuo codice con commenti esplicativi, questo riduce la leggibilità sia del codice che delle spiegazioni! –

1

ho finito per fare questa funzione utilizzando alcune funzioni da altre persone in questa pagina. Ho modificato quello da Joanna Goch il modo in cui Peter Brand dice per lo più, e anche aggiunto del codice da Guest e da altri luoghi.

Questa funzione non utilizza un'estensione e non utilizza appendXML (che è molto schizzinosa e interrompe anche se vede un tag BR che non è chiuso) e sembra funzionare correttamente.

function set_inner_html($element, $content) { 
    $DOM_inner_HTML = new DOMDocument(); 
    $internal_errors = libxml_use_internal_errors(true); 
    $DOM_inner_HTML->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8')); 
    libxml_use_internal_errors($internal_errors); 
    $content_node = $DOM_inner_HTML->getElementsByTagName('body')->item(0); 
    $content_node = $element->ownerDocument->importNode($content_node, true); 
    while ($element->hasChildNodes()) { 
     $element->removeChild($element->firstChild); 
    } 
    $element->appendChild($content_node); 
} 
Problemi correlati