2010-05-06 4 views
10

Comment modifier innerHTML d'un phome DOMElement?Modifier innerHTML d'un php DOMElement

+0

Vous ne pouvez pas, directement. Vous devrez avoir une fonction intermédiaire pour prendre une chaîne et la transformer en un tableau de DOMElements. Vous pouvez l'écrire vous-même, même si je suis sûr que quelque chose comme ça existe sur le web. –

+0

Il n'y a pas de propriété innerHTML dans la classe php DOMElement. Essayez de regarder ici: http://php.net/manual/en/class.domelement.php et ici: http://www.php.net/manual/en/class.domtext.php – Babiker

Répondre

0

Jetez un oeil à cette bibliothèque PHP Simple HTML DOM Parser http://simplehtmldom.sourceforge.net/

Il semble assez simple. Vous pouvez modifier la propriété innertext de vos éléments. Cela pourrait aider.

+1

PHP, pas JavaScript .. L'implémentation de DOM par PHP n'a pas de propriété 'innerHTML'. –

+1

oui, ma faute. mais l'interpréteur DOM du php5 HTML a 'innertext'. http://simplehtmldom.sourceforge.net/ – Jull

+0

Ce n'est pas la bibliothèque à laquelle l'OP faisait référence. Voir: http://php.net/manual/fr/book.dom.php Mais vous pouvez éditer votre réponse et le lier à la bibliothèque que vous avez trouvée et voir si l'OP veut changer. –

1

Je pense que la meilleure chose que vous pouvez faire est de venir avec une fonction qui prendra la DOMElement que vous voulez changer le InnerHTML de, copier, et de le remplacer.

En PHP très rude:

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

    return $newElement; 
} 

Cela ne prend pas en compte des attributs et des structures imbriquées, mais je pense que cela va vous sur votre chemin.

+2

Pour quelqu'un d'autre essayant ce code - je devais utiliser $ el-> parentNode-> insertBefore au lieu de $ el-> insertBefore. – whichdan

+0

Cela fonctionne pour définir innerText pas innerHTML. Le 2ème param de createElement n'accepte pas le formatage html. – Greg

+0

D'accord, @greg. Cela va encoder les caractères HTML. – Kafoso

7

je devais le faire pour un projet récemment et a fini avec une extension DOMElement: http://www.keyvan.net/2010/07/javascript-like-innerhtml-access-in-php/

Voici un exemple montrant comment il est utilisé:

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

est ici un remplacement par la fonction de classe I vient d'écrire:

Il va remplacer le innerHtml d'une classe. Vous pouvez également spécifier le type de noeud, par exemple. div/p/a etc.

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

Voici une autre fonction que j'ai écrit pour supprimer des nœuds avec une classe spécifique, mais en conservant le code html interne.

La définition de remplacer à true supprimera le code HTML interne.

Réglage à remplacer tout autre contenu remplacera le code html interne avec le contenu fourni. Ces fonctions peuvent facilement être adaptées pour utiliser d'autres attributs en tant que sélecteur. J'en avais seulement besoin pour évaluer l'attribut de la classe.

1

Il semble que appendXML ne fonctionne pas toujours - par exemple, si vous essayez d'ajouter XML avec 3 niveaux.Voici la fonction que j'ai écrit que le travail toujours (vous voulez définir $ contenu en innerHTML à $ 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 variable '$ elementNode' retournée est indéfinie - ne devrait-elle pas être' $ contentNode'? Vous pouvez simplifier la fonction en utilisant '$ element-> ownerDocument' au lieu d'avoir à passer dans' $ DOM'. Ceci importe uniquement le premier enfant de tout contenu $ contenu. Pour importer le fragment entier, supprimez le '-> firstChild 'sur la ligne 4. –

-1

Voici comment vous le faites:

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

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

echo $doc->saveHTML(); 
0

développement sur de la réponse de Joanna Goch , cette fonction insère un noeud de texte ou un fragment 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; 
} 

utilisation

$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

Une autre solution:

1) créer un nouveau DOMDocumentFragment de la chaîne HTML à insérer; 2) supprimer l'ancien contenu de notre élément en supprimant ses nœuds enfants; 3) ajouter DOMDocumentFragment à notre élément.

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

Sinon, nous pouvons remplacer notre élément avec son clean copy puis ajoutez DOMDocumentFragment à ce 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); 
} 

Test:

$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

Bien que cet extrait de code puisse résoudre la question, [y compris une explication] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) aide vraiment à améliorer la qualité de votre message. Rappelez-vous que vous répondez à la question pour les lecteurs dans le futur, et que ces personnes pourraient ne pas connaître les raisons de votre suggestion de code. Essayez également de ne pas surcharger votre code avec des commentaires explicatifs, ceci réduit la lisibilité du code et des explications! –

1

J'ai fini par faire cette fonction en utilisant quelques fonctions d'autres personnes sur cette page. J'ai changé celui de Joanna Goch la façon dont Peter Brand dit la plupart, et a également ajouté du code de Guest et d'autres endroits.

Cette fonction n'utilise pas d'extension et n'utilise pas appendXML (qui est très pointilleux et se casse même si elle voit une balise BR non fermée) et semble fonctionner correctement.

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