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.

Boldewyn
fonte
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.

CMS
fonte
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

gtournie
fonte
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;
Shishir Arora
fonte
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;
   }
}
Bryan Kyle
fonte
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

Rich Apodaca
fonte
3

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

Pavel V.
fonte
1

Se o seu elemento tem pai

element.parentElement.innerHTML
Vincnetas
fonte
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);
Alex Popa
fonte
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

Aaron
fonte
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;
        },
Balagan
fonte
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;
victorkurauchi
fonte
.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