innerHTML unencodes < in attributes

Try XMLSerializer:

var div = document.getElementById('d1');

var pre = document.createElement('pre');
pre.textContent = div.outerHTML;
document.body.appendChild(pre);

pre = document.createElement('pre');
pre.textContent = new XMLSerializer().serializeToString(div);
document.body.appendChild(pre);
<div id="d1" data-foo="a &lt; b &amp;&amp; b &gt; c">This is a test</div>

You might need to adapt the XSLT to take account of the XHTML namespace XMLSerializer inserts (at least here in a test with Firefox).