繁体   English   中英

DOMParser 附加<script> tags to <head>/<body> but not executing

[英]DOMParser appending <script> tags to <head>/<body> but not executing

我试图通过 DOMParser 将一个字符串解析为一个完整的 HTML 文档,然后用处理过的节点覆盖当前页面。 该字符串包含完整的标记,包括<!doctype><html><head><body>节点。

// parse the string into a DOMDocument element:
var parser = new DOMParser();
var doc = parser.parseFromString(data, 'text/html');

// set the parsed head/body innerHTML contents into the current page's innerHTML
document.getElementsByTagName('head')[0].innerHTML = doc.getElementsByTagName('head')[0].innerHTML;
document.getElementsByTagName('body')[0].innerHTML = doc.getElementsByTagName('body')[0].innerHTML;

这是因为它成功地获取了已解析的 HTML 节点并将它们呈现在页面上; 但是,解析字符串内的<head><body>节点中存在的任何<script>标记都无法执行 =[。 直接使用html标签(与head / body相对)进行测试会产生相同的结果。

我也尝试过使用.appendChild()而不是.innerHTML() ,但没有改变:

var elementHtml = document.getElementsByTagName('html')[0];

// remove the existing head/body nodes from the page
while (elementHtml.firstChild) elementHtml.removeChild(elementHtml.firstChild);

// append the parsed head/body tags to the existing html tag
elementHtml.appendChild(doc.getElementsByTagName('head')[0]);
elementHtml.appendChild(doc.getElementsByTagName('body')[0]);

有谁知道将字符串转换为完整的 HTML 页面执行其中包含的 javascript 的方法吗?

如果有替代 DOMParser 的方法可以提供相同的结果(例如覆盖整个文档),请随时推荐它/它们 =]

注意
我使用它而不是更简单的document.write(data)替代方案的原因是因为我需要在 SSL 下的 IE 中的postMessage()回调中使用它; document.write()在 IE 中访问 SSL 页面时在回调事件中被阻止,例如发布消息 =[

你应该使用:

const sHtml = '<script>window.alert("Hello!")</script>';
const frag = document.createRange().createContextualFragment(sHtml)
document.body.appendChild( frag );

使用问题中描述的DOMParser()将正确设置页面的<head><body>内容,但需要更多的工作来执行任何现有的<script>标签。

这里的基本方法是在设置内容后拉出页面中所有<script>标签的列表,迭代该列表并使用现有内容动态创建一个新的<script>标签,然后添加新的一页。

例子:

// 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]);
    }
}

这是 jQuery 1.8.3 的工作演示(链接到 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"));
});

因此,我使用了$.parseXML()函数,如果您的 HTML 也是有效的 XML,那么您显然只能使用该函数。 不幸的是,相同的代码不适用于 jQuery 1.9.1(不再找到<script>标签): http : //jsfiddle.net/6cECR/8/也许它是一个错误(或一个安全特性......)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM