Obtenir la représentation sous forme de chaîne d'un nœud DOM

97

Javascript: J'ai la représentation DOM d'un nœud (élément ou document) et je cherche la représentation sous forme de chaîne de celui-ci. Par exemple,

var el = document.createElement("p");
el.appendChild(document.createTextNode("Test"));

devrait céder:

get_string(el) == "<p>Test</p>";

J'ai le sentiment fort, qu'il me manque quelque chose de trivialement simple, mais je ne trouve tout simplement pas de méthode qui fonctionne dans IE, FF, Safari et Opera. Par conséquent, externalHTML n'est pas une option.

Boldewyn
la source
4
Avec vraisemblablement la version 11, Firefox prend également en charge externalHTML
Boldewyn
1
Pour l'instant, il semble que IE, FF, Safari, Chrome, Opera prennent tous en charge le
HTML externe
1
Oui, c'est maintenant (depuis 2009, c'est-à-dire) devenu une tâche triviale :)
Boldewyn
Oui, certainement
externeHTML

Réponses:

134

Vous pouvez créer un nœud parent temporaire et en obtenir le contenu innerHTML:

var el = document.createElement("p");
el.appendChild(document.createTextNode("Test"));

var tmp = document.createElement("div");
tmp.appendChild(el);
console.log(tmp.innerHTML); // <p>Test</p>

EDIT: Veuillez voir la réponse ci-dessous à propos de externalHTML. el.outerHTML devrait être tout ce qui est nécessaire.

Christian C. Salvadó
la source
1
Aie. Si simple ... Juste une petite note: si je veux que le document entier soit "stringifié", je peux utiliser la même méthode avec document.documentElement (cas d'utilisation: requêtes AJAX). Peut-être pourriez-vous intégrer cela dans la réponse?
Boldewyn
3
@Boldewyn: vous pouvez ajouter le tout document.documentElementdans un div? Holy crap ....
Roatin Marth
Simple, as hell ... +1 Trop mauvais documentFragment ne prend pas en charge innerHTML
Lajos Meszaros
30
externalHTML est la réponse
neaumusic
3
N'oubliez pas de cloner votre elementavant de l'ajouter, tmpcar lorsque vous l'ajouterez tmp, il sera supprimé document.
Olcay Ertaş
45

Ce que vous recherchez, c'est «externalHTML», mais nous avons besoin d'une solution de secours car elle n'est pas compatible avec les anciens navigateurs.

var getString = (function() {
  var DIV = document.createElement("div");

  if ('outerHTML' in DIV)
    return function(node) {
      return node.outerHTML;
    };

  return function(node) {
    var div = DIV.cloneNode();
    div.appendChild(node.cloneNode(true));
    return div.innerHTML;
  };

})();

// getString(el) == "<p>Test</p>"

Vous trouverez mon plugin jQuery ici: Obtenez le HTML externe de l'élément sélectionné

gtournie
la source
Firefox ajouté outerHTMLdans la version 11, après avoir posé la question. Ce n'était donc pas une option à l'époque. J'ai même mis à jour ma question avec un commentaire approprié, si vous regardez attentivement.
Boldewyn
Ce droit, vous coz de déposer id élément et autres attrs si l' utilisationinnerHtml
Sergei Panfilov
1
@SergeyPanfilov: Je n'ai rien laissé tomber parce que j'ai enveloppé le nœud dans un div vide avant d'appeler innerHTML; )
gtournie
3
En 2015, je dirais que c'est de loin la meilleure réponse.
ACK_stoverflow
Oui, à ce jour, seuls les navigateurs très anciens (IE> 10, Safari> 7, vraiment ancien FF, Chrome) et / ou obscurs (Opera Mini) ne prennent pas en charge l' outerHTMLattribut. Voir aussi caniuse.com/#feat=xml-serializer
Gert Sønder du
20

Je ne pense pas que vous ayez besoin d'un script compliqué pour cela. Juste utiliser

get_string=(el)=>el.outerHTML;
Shishir Arora
la source
c'est la meilleure réponse
Avraham
15

Sous FF, vous pouvez utiliser l' XMLSerializerobjet pour sérialiser XML en une chaîne. IE vous donne une xmlpropriété d'un nœud. Vous pouvez donc faire ce qui suit:

function xml2string(node) {
   if (typeof(XMLSerializer) !== 'undefined') {
      var serializer = new XMLSerializer();
      return serializer.serializeToString(node);
   } else if (node.xml) {
      return node.xml;
   }
}
Bryan Kyle
la source
FYI .xmlne fonctionne pas sur les nœuds DOM (comme dans les nœuds de la page actuelle). Cela ne fonctionne que sur les nœuds de document XML DOM.
Crescent Fresh
Et inversement, outerHTMLne fonctionne pas sur les nœuds de document XML DOM. Cela ne fonctionne que sur les nœuds DOM (comme dans les nœuds de la page actuelle). Bonne cohérence là je dirais.
Crescent Fresh
7

Utilisez l'élément # externalHTML:

var el = document.createElement("p");
el.appendChild(document.createTextNode("Test"));

console.log(el.outerHTML);

Il peut également être utilisé pour écrire des éléments DOM. De la documentation de Mozilla:

L'attribut externalHTML de l'interface DOM d'élément obtient le fragment HTML sérialisé décrivant l'élément, y compris ses descendants. Il peut être défini pour remplacer l'élément par des nœuds analysés à partir de la chaîne donnée.

https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML

Rich Apodaca
la source
3

Utilisez element.outerHTML pour obtenir une représentation complète de l'élément, y compris les balises externes et les attributs.

Pavel V.
la source
1

Si votre élément a un parent

element.parentElement.innerHTML
Vincnetas
la source
2
Merci d'avoir répondu! Malheureusement, cela a déjà été suggéré, mais le répondant a supprimé la réponse. Le problème est que le parent peut contenir beaucoup plus de balisage que souhaité. Pensez à externalHTML pour un seul <li>dans une liste.
Boldewyn
1

Essayer

new XMLSerializer().serializeToString(element);
Alex Popa
la source
Merci pour la suggestion, mais c'est exactement ce que Bryan Kale a suggéré dans sa réponse.
Boldewyn
1

J'ai trouvé que pour mes cas d'utilisation, je ne veux pas toujours l'intégralité du HTML externe. De nombreux nœuds ont juste trop d'enfants à afficher.

Voici une fonction (testée au minimum dans Chrome):

/**
 * Stringifies a DOM node.
 * @param {Object} el - A DOM node.
 * @param {Number} truncate - How much to truncate innerHTML of element.
 * @returns {String} - A stringified node with attributes
 *                     retained.
 */
function stringifyEl(el, truncate) {
    var truncateLen = truncate || 50;
    var outerHTML = el.outerHTML;
    var ret = outerHTML;
    ret = ret.substring(0, truncateLen);

    // If we've truncated, add an elipsis.
    if (outerHTML.length > truncateLen) {
      ret += "...";
    }
    return ret;
}

https://gist.github.com/kahunacohen/467f5cc259b5d4a85eb201518dcb15ec

Aaron
la source
0

J'ai perdu beaucoup de temps à déterminer ce qui ne va pas lorsque j'itère dans DOMElements avec le code dans la réponse acceptée. C'est ce qui a fonctionné pour moi, sinon chaque deuxième élément disparaît du document:

_getGpxString: function(node) {
          clone = node.cloneNode(true);
          var tmp = document.createElement("div");
          tmp.appendChild(clone);
          return tmp.innerHTML;
        },
balagan
la source
1
Je ne me dis pas, quand je suppose, que vous avez un problème différent ici. Notez que la solution ci-dessus supprime l'élément d'origine du DOM. Ainsi, lorsque vous utilisez une collection live comme document.getElementsByTagName(), cette collection changera à mi- forboucle, d'où le saut de chaque deuxième élément.
Boldewyn
-1

si vous utilisez react:

const html = ReactDOM.findDOMNode(document.getElementsByTagName('html')[0]).outerHTML;
victorkurauchi
la source
.outerHTMLn'est pas spécifique à React; c'est un standard DOM. Découvrez la réponse de @Rich Apodaca.
chharvey
oui ... le point d'intérêt (si vous utilisez react) sur ma réponse était reactdom.findDOMNode()..., pas le .outerHTML, mais merci pour la position.
victorkurauchi