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.