129

Javascript: I have the DOM representation of a node (element or document) and I'm looking for the string representation of it. E.g.,

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

should yield:

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

I have the strong feeling, that I'm missing something trivially simple, but I just don't find a method that works in IE, FF, Safari and Opera. Therefore, outerHTML is no option.

El Developer
  • 3,345
  • 1
  • 21
  • 40
Boldewyn
  • 81,211
  • 44
  • 156
  • 212

13 Answers13

166

You can create a temporary parent node, and get the innerHTML content of it:

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: Please see answer below about outerHTML. el.outerHTML should be all that is needed.

hbhakhra
  • 4,206
  • 2
  • 22
  • 36
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • 2
    Ouch. So simple... Just a little note: If I want the whole document "stringified", I can use the same method with document.documentElement (usecase: AJAX requests). Perhaps you could incorporate that in the answer? – Boldewyn Nov 17 '09 at 18:36
  • 4
    @Boldewyn: you can append the entire `document.documentElement` into a div? Holy crap.... – Roatin Marth Nov 17 '09 at 19:23
  • 1
    Simple, as hell... +1 Too bad documentFragment does not support innerHTML – Lajos Mészáros Jul 19 '13 at 13:53
  • This appears to omit the elements' attributes, like `class`. Any way to get those in the output? – JellicleCat Jul 10 '15 at 04:09
  • 46
    outerHTML is the answer – neaumusic Jul 23 '15 at 07:14
  • I had an array of nodes (from jQuery's parseHTML function), and was able to simply map across them with a function extracting `outerHTML`, and then join the resulting array of strings with no separator. The result was an HTML string equivalent to what I had put in, but containing the subsequent changes I had applied to the nodes. – Gert Sønderby Aug 12 '15 at 09:50
  • 4
    Don't forget to clone your `element` before adding it to `tmp` becouse when you add it to `tmp`, it will be removed from `document`. – Olcay Ertaş Aug 27 '16 at 11:14
  • This have to be best answer: https://stackoverflow.com/a/35913488/2179748 – WebBrother Dec 05 '17 at 10:30
  • if you want the tag too, outerHTML is the correct answer – k33g_org Feb 24 '18 at 05:29
59

What you're looking for is 'outerHTML', but we need a fallback because it's not compatible with old browsers.

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

You'll find my jQuery plugin here: Get selected element's outer HTML

Jasperan
  • 2,154
  • 1
  • 16
  • 40
gtournie
  • 4,143
  • 1
  • 21
  • 22
  • Firefox added `outerHTML` in version 11, after I asked the question. So that wasn't an option back then. I even updated my question with an appropriate comment, if you look closely. – Boldewyn Nov 19 '13 at 22:25
  • This right, coz you drop element id's and other attrs if use `innerHtml` – S Panfilov Jun 05 '15 at 08:23
  • 1
    @SergeyPanfilov: I didn't drop anything because I wrapped the node in an empty div before calling `innerHTML` ; ) – gtournie Jun 05 '15 at 14:35
  • 3
    In 2015, I would say this is far and away the best answer. – ACK_stoverflow Jul 24 '15 at 12:19
  • Yeah, as of today, only very old (IE>10,Safari >7, truly ancient FF, Chrome) and/or obscure browsers (Opera Mini) do not support the `outerHTML` attribute. See also http://caniuse.com/#feat=xml-serializer – Gert Sønderby Aug 12 '15 at 09:54
  • Simply `document.documentElement.outerHTML;` if you don't care about old browsers. – Wa. Feb 19 '18 at 23:04
26

I dont think you need any complicated script for this. Just use

get_string=(el)=>el.outerHTML;
Shishir Arora
  • 5,521
  • 4
  • 30
  • 35
22

Under FF you can use the XMLSerializer object to serialize XML into a string. IE gives you an xml property of a node. So you can do the following:

function xml2string(node) {
   if (typeof(XMLSerializer) !== 'undefined') {
      var serializer = new XMLSerializer();
      return serializer.serializeToString(node);
   } else if (node.xml) {
      return node.xml;
   }
}
Bryan Kyle
  • 13,361
  • 4
  • 40
  • 45
  • FYI `.xml` doesn't work on DOM nodes (as in nodes in the current page). It only works on XML DOM document nodes. – Crescent Fresh Nov 17 '09 at 18:47
  • And conversely, `outerHTML` doesn't work on XML DOM document nodes. It only works on DOM nodes (as in nodes in the current page). Good consistency there I'd say. – Crescent Fresh Nov 17 '09 at 18:53
9

Use Element#outerHTML:

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

console.log(el.outerHTML);

It can also be used to write DOM elements. From Mozilla's documentation:

The outerHTML attribute of the element DOM interface gets the serialized HTML fragment describing the element including its descendants. It can be set to replace the element with nodes parsed from the given string.

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

Rich Apodaca
  • 28,316
  • 16
  • 103
  • 129
6

Try

new XMLSerializer().serializeToString(element);
Alex Popa
  • 101
  • 1
  • 5
3

Use element.outerHTML to get full representation of element, including outer tags and attributes.

Pavel V.
  • 91
  • 3
3

You can simply use outerHTML property over the element. It will return what you desire.

Let's create a function named get_string(element)

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

function get_string(element) {
 console.log(element.outerHTML);
}

get_string(el); // your desired output
enter image description here
Satish Chandra Gupta
  • 2,970
  • 1
  • 22
  • 22
2

If your element has parent

element.parentElement.innerHTML
Vincnetas
  • 146
  • 1
  • 4
  • 3
    Thanks for the answer! Unfortunately that was already suggested, but the answerer deleted the answer. The problem is, that the parent might contain a lot _more_ markup than wanted. Think of outerHTML for a single `
  • ` in a list.
  • – Boldewyn Jan 02 '15 at 13:12