I\'m attempting to parse a string into a full HTML document via DOMParser and then overwrite the current page with the processed nodes. The string contains complete markup,
You should use:
const sHtml = '<script>window.alert("Hello!")</script>';
const frag = document.createRange().createContextualFragment(sHtml)
document.body.appendChild( frag );
Using DOMParser()
as described in the question will correctly set the <head>
and <body>
contents of the page, but more work is necessary to get any existing <script>
tags to execute.
The basic approach here is to pull a list of all <script>
tags in the page after the contents have been set, iterate over that list and dynamically create a new <script>
tag with the contents of the existing one and then add the new one to the page.
Example:
// create a DOMParser to parse the HTML content
var parser = new DOMParser();
var parsedDocument = parser.parseFromString(data, 'text/html');
// set the current page's <html> contents to the newly parsed <html> content
document.getElementsByTagName('html')[0].innerHTML = parsedDocument.getElementsByTagName('html')[0].innerHTML;
// get a list of all <script> tags in the new page
var tmpScripts = document.getElementsByTagName('script');
if (tmpScripts.length > 0) {
// push all of the document's script tags into an array
// (to prevent dom manipulation while iterating over dom nodes)
var scripts = [];
for (var i = 0; i < tmpScripts.length; i++) {
scripts.push(tmpScripts[i]);
}
// iterate over all script tags and create a duplicate tags for each
for (var i = 0; i < scripts.length; i++) {
var s = document.createElement('script');
s.innerHTML = scripts[i].innerHTML;
// add the new node to the page
scripts[i].parentNode.appendChild(s);
// remove the original (non-executing) node from the page
scripts[i].parentNode.removeChild(scripts[i]);
}
}
Here is a working demo for jQuery 1.8.3 (link to jsFiddle):
var html = "<html><head><script>alert(42);</" + "script></head><body><h1>Hello World</h1></body></html>";
$(function () {
html = $($.parseXML(html));
$("head").append(html.find("script"));
$("body").append(html.find("h1"));
});
Thereby I used the function $.parseXML()
which you only can use obviously, if your HTML is also valid XML. Unfortunately is the same code not working with jQuery 1.9.1 (the <script>
tag is not found anymore): http://jsfiddle.net/6cECR/8/ Maybe its a bug (or a security fetaure...)