在iframe中加载XSLTProcessor :: transformToDocument()的输出时未执行Javascript

时间:2018-09-11 09:15:40

标签: javascript html xslt

我正在将XSLTProcessor :: transformToDocument()的输出(HTMLDocument)加载到iframe中。

HTML可以正确呈现,但是输出中存在的Javascript不会执行/触发(下面是FF检查器输出)

<iframe id="output-frame"></iframe>
#document
<html> 
   <head></head>    
   <body onload="console.log('hello')">Hello</body>
</html>

如果我改为引用静态html文件,则可以正常工作:

<iframe id="output-frame" src="iframe.html"></iframe>
#document
<html> 
   <head></head>    
   <body onload="console.log('hello')">Hello</body>
</html>

是否有一种技术可以显式触发内部javascript?

问题可能来自technique I'm using,将HTMLDocument加载到iframe中:

var doc = xsltProcessor.transformToDocument(xml);
var frame = document.getElementById("output-frame");
var destDocument = frame.contentDocument;
var srcNode = doc.documentElement;
var newNode = destDocument.importNode(srcNode, true);
destDocument.replaceChild(newNode, destDocument.documentElement);

我真的不需要使用iframe,我可以用transformToDocument()的结果替换当前页面。

我正在FF62中进行测试。

[更新]我发现External JavaScript doesn't work in iFrames?看起来很相关。

我尝试在iframe上指定相同的原始src(稍后将在我的转换输出中覆盖),但这无济于事。

有人知道如何在FF中记录“同源”冲突/冲突吗?

1 个答案:

答案 0 :(得分:0)

这是一个解决方案,可让您将iframe的源设置为所需的任何对象(包括由XSLTProcessor::transformToDocument()创建的HTML文档)。

  1. 创建一个Blob对象并将其传递给URL.createObjectURL(blob)
  2. 将您的iframe src设置为返回的网址

浏览器将获取指定的资源,并像处理其他资源一样对其进行处理。对于HTML文档,这意味着包含的<script><style>元素将按照您的期望进行评估。

对于您的具体用例,它看起来像这样:

let xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);

let htmlDoc = xsltProcessor.transformToDocument(xml);
let htmlDocStr = new XMLSerializer().serializeToString(htmlDoc);

const getBlobURL = (code, type) => {
    const blob = new Blob([code], { type })
    return URL.createObjectURL(blob)
}

document.getElementById("my-iframe").src = getBlobURL(htmlDocStr, 'text/html');

查看this blog post以获得一些背景信息。