Obtenha a representação de string de um nó DOM


96

Javascript: eu tenho a representação DOM de um nó (elemento ou documento) e estou procurando a representação de string dele. Por exemplo,

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

deve render:

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

Tenho a forte sensação de que estou perdendo algo trivialmente simples, mas simplesmente não encontro um método que funcione no IE, FF, Safari e Opera. Portanto, outerHTML não é uma opção.


4
Com presumivelmente a versão 11, o Firefox também suporta outerHTML: bugzilla.mozilla.org/show_bug.cgi?id=92264
— Boldewyn

1
Por enquanto, parece que IE, FF, Safari, Chrome, Opera todos suportam outerHTML, consulte developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
— wangf

1
Sim, agora (isto é, desde 2009) se tornou uma tarefa trivial :)
— Boldewyn,

Sim, definitivamente outerHTML
— neaumusic

Respostas:


133

Você pode criar um nó pai temporário e obter o conteúdo interno de HTML dele:

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: Por favor, veja a resposta abaixo sobre outerHTML. el.outerHTML deve ser tudo o que você precisa.


1
Ai. Tão simples ... Só uma pequena nota: Se eu quiser todo o documento "stringificado", posso usar o mesmo método com document.documentElement (usecase: solicitações AJAX). Talvez você possa incorporar isso na resposta?
— Boldewyn

3
@Boldewyn: você pode anexar tudo document.documentElementem um div? Puta merda ...
— Roatin Marth

Simples como o inferno ... +1 Pena que o documentFragment não suporta o innerHTML
— Lajos Meszaros

30
outerHTML é a resposta
— neaumusic

3
Não se esqueça de clonar o seu elementantes de adicioná-lo, tmpporque ao adicioná-lo tmp, ele será removido document.
— Olcay Ertaş

44

O que você está procurando é 'outerHTML', mas precisamos de um substituto porque não é compatível com navegadores antigos.

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

Você encontrará meu plugin jQuery aqui: Obter HTML externo do elemento selecionado


Firefox adicionado outerHTMLna versão 11, depois que fiz a pergunta. Então essa não era uma opção. Até atualizei minha pergunta com um comentário apropriado, se você olhar de perto.
— Boldewyn de

Isso, porque você elimina os ids dos elementos e outros atributos se usarinnerHtml
— Sergei Panfilov

1
@SergeyPanfilov: Não eliminei nada porque envolvi o nó em uma div vazia antes de chamar innerHTML; )
— gtournie

3
Em 2015, eu diria que esta é de longe a melhor resposta.
— ACK_stoverflow

Sim, a partir de hoje, apenas navegadores muito antigos (IE> 10, Safari> 7, FF verdadeiramente antigo, Chrome) e / ou navegadores obscuros (Opera Mini) não suportam o outerHTMLatributo. Veja também caniuse.com/#feat=xml-serializer
— Gert Sønderby

20

Eu não acho que você precisa de nenhum script complicado para isso. Apenas use

get_string=(el)=>el.outerHTML;

esta é a melhor resposta
— Avraham

15

No FF, você pode usar o XMLSerializerobjeto para serializar XML em uma string. O IE oferece uma xmlpropriedade de um nó. Portanto, você pode fazer o seguinte:

function xml2string(node) {
   if (typeof(XMLSerializer) !== 'undefined') {
      var serializer = new XMLSerializer();
      return serializer.serializeToString(node);
   } else if (node.xml) {
      return node.xml;
   }
}

FYI .xmlnão funciona em nós DOM (como em nós na página atual). Ele só funciona em nós de documentos XML DOM.
— Crescent Fresh

E, inversamente, outerHTMLnão funciona em nós de documentos XML DOM. Ele só funciona em nós DOM (como em nós na página atual). Boa consistência aí, eu diria.
— Crescent Fresh

7

Use o elemento # outerHTML:

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

console.log(el.outerHTML);

Também pode ser usado para escrever elementos DOM. Da documentação da Mozilla:

O atributo outerHTML da interface DOM do elemento obtém o fragmento HTML serializado que descreve o elemento, incluindo seus descendentes. Ele pode ser configurado para substituir o elemento por nós analisados ​​a partir da string fornecida.

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


3

Use element.outerHTML para obter a representação completa do elemento, incluindo tags externas e atributos.


1

Se o seu elemento tem pai

element.parentElement.innerHTML

2
Obrigado pela resposta! Infelizmente, isso já foi sugerido, mas o respondente excluiu a resposta. O problema é que o pai pode conter muito mais marcação do que o desejado. Pense em outerHTML para um único <li>em uma lista.
— Boldewyn

1

Experimentar

new XMLSerializer().serializeToString(element);

Obrigado pela sugestão, mas foi exatamente isso que Bryan Kale sugeriu em sua resposta.
— Boldewyn

1

Descobri que, para meus casos de uso, nem sempre quero todo o outerHTML. Muitos nós simplesmente têm muitos filhos para mostrar.

Esta é uma função (minimamente testada no 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


0

Perdi muito tempo tentando descobrir o que há de errado ao iterar por meio do DOMElements com o código da resposta aceita. Isso é o que funcionou para mim, caso contrário, cada segundo elemento desaparece do documento:

_getGpxString: function(node) {
          clone = node.cloneNode(true);
          var tmp = document.createElement("div");
          tmp.appendChild(clone);
          return tmp.innerHTML;
        },

1
Não me arrisco, suponho, que você tenha um problema diferente aqui. Observe que a solução acima remove o elemento original do DOM. Então, quando você usa uma coleção ativa como document.getElementsByTagName(), essa coleção mudará no meio do forloop, portanto, o salto de cada segundo elemento.
— Boldewyn

-1

se estiver usando o react:

const html = ReactDOM.findDOMNode(document.getElementsByTagName('html')[0]).outerHTML;

.outerHTMLnão é específico do React; é um padrão DOM. Confira a resposta de @Rich Apodaca.
— chharvey

sim ... o ponto de interesse (se estiver usando react) na minha resposta foi reactdom.findDOMNode()..., não o .outerHTML, mas obrigado pela posição.
— victorkurauchi
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.