如何在不替换字符的情况下获取iframe的body标记中包含的html

How can I get the html contained in the body tag of an iframe without it replacing characters?

本文关键字:body html 包含 iframe 情况下 替换 字符 获取      更新时间:2023-09-26

我目前正在尝试在浏览器不破坏内容的情况下获取iframe主体的内容。

我可以通过将内容包含在文本区域来实现,但我希望避免这种情况。

使用.nernerHTML会导致特殊字符(如<>&(分别转换为&lt;&gt;&amp;

要进行测试,请构建一个包含以下内容的html文件:

{ 
 "id": 5, 
 "testtext":"I am > than this & < that", 
 "html":"<div>'"worky'"</div>" 
}

然后在iframe:中包含该文件的另一个页面

<!doctype html>
<html>
  <head>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
  </head>
  <body>
    <iframe id="myIframe" name="myIframe" src="test.html"></iframe><br />
    Result:<br />
    <textarea id='result'></textarea>
    <script>
      $("#myIframe").load(function(){
        var iframeBody = window.frames.myIframe.document
            .getElementsByTagName("body")[0], result;
        result = iframeBody.innerHTML;
        $("#result").val(result);
      });
    </script>
  </body>
</html>

我试过这个:

result = $(iframeBody).contents().map(function(){
      return this.nodeValue ? this.nodeValue : this.innerHTML;
}).get().join("");

然而它失去了分配

编辑:

我有一个解决方案,

var iframeBody, result;
$("#myIframe").load(function(){
  iframeBody = window.frames.myIframe.document
    .getElementsByTagName("body")[0];
  result = $(iframeBody).contents().map(function(){
    if (this.nodeValue) {
        return this.nodeValue   
    }
    else {
        return $(this).clone().wrap('<p>').parent().html();
    }
  }).get().join("");
  $("#result").val(result);
});

然而,它仍然会在html中对非html的内容进行编码。我不确定我是否同意。

再次编辑

这里有更多的上下文。我正在修改jquery iframe ajax传输,以便在内容不是html时不需要iframe中的文本区域来保存内容。在大多数情况下,它在没有文本区域的情况下工作得很好,但当你使用.innerHTML检索文本时,它会破坏任何特殊的html字符。避免破坏的一种方法是使用.nodeValue获取文本,但当遇到html元素时,这是不起作用的。如果您出于任何原因返回包含html字符串的json,它需要能够提取该json字符串,就像它在iframe中返回的一样,这意味着保留所有字符。

为了测试的目的,这个jsfiddle已经足够测试了。假设fiddle中使用的div是iframe的主体,您可以在jsfiddle上测试结果。我遇到的问题实际上与iframe或它的加载事件无关。

http://jsfiddle.net/P623a/2/

在这把小提琴里,唯一的问题是&被转换为&json中div的内部。

解决方案

如果响应是json/jsonp/script并包含dom元素,我只需要对页面进行正确编码(application/json、script或纯文本(。如果在这些条件下没有正确编码,就会触发错误处理程序。

如果编码正确,iframe最终会有一个包含<pre>your content</pre>的body标记,您可以在保留特殊字符的同时获得使用.innerText的内容。

浏览器将iframe中的数据解释为HTML,据我所知,没有方法来获取原始文本(àla view source(。

以下是我可以想出的选项:

  • 使响应成为有效的HTML——将其包装在文档中,并对所需的数据进行编码,类似于以下内容:

    <!DOCTYPE html>
    <html>
    <head>
    <body>
    { 
     "id": 5, 
     "testtext":"I am &gt; than this &amp; &lt; that", 
     "html":"&lt;div&gt;'"worky'"&lt;/div&gt;" 
    }
    
  • 使用MIME类型发送响应,不会被解释为HTML,如application/jsontext/plain。浏览器可能会围绕它构建一个文档(比如将数据放在pre中(,你也可以用同样的方式获取它。

在任何一种情况下,您都可以访问文档的innerText(或textContent,取决于浏览器(或包含数据的文本节点的nodeValue,如下所示:

var iframeBody = iframe.contentDocument.body,
    json = iframeBody.textContent || iframeBody.innerText;

test1.html中的代码没有"body",如果没有body,就不能.getElementsByTagName("body")。尝试:

$("#myIframe").load(function(){
    $("#result").val($(this).contents().text());
});

您正在将iframe加载事件处理程序设置在已经具有源的iframe标记之后。因此,在附加load事件处理程序之前加载iframe是可能的。我并不是说这就是问题所在,但如果iframe快速加载,这将产生问题。您可以在iframe标记本身中提供一个内联加载事件处理程序。

试试这个

<!doctype html>
<html>
  <head>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script type="text/javascript">
    function copyIframeContent(iframe){
        var iframeContent = $(iframe).contents();
        $("#result").html(iframeContent.find('body').html());
    }
    </script>
  </head>
  <body>
    <iframe id="myIframe" onload="copyIframeContent(this);" name="myIframe" src="test.html"></iframe><br />
    Result:<br />
    <textarea id='result'></textarea>
  </body>
</html>

我希望这对你有帮助。

我认为如果你计划使用nodeValue,你必须首先尝试一个有效的html,否则,你不能假设浏览器会为你添加正文,这根本不是html:

{ 
 "id": 5, 
 "testtext":"I am > than this & < that", 
 "html":"<div>'"worky'"</div>" 
}

尝试解析一个不是html的dom是很奇怪的!事实是,如果你想有机会使用jQuery进行操作或遍历,你至少必须将所有东西包装在一个大容器中,比如:

<div>
// even if you don't want use body or html tag, things must be wrapped here
</div>

我认为存在一个误解的问题,即你试图满足你的需求的内容和方式,加载一些json(就像你写的那样(不应该更容易吗?!你正试图滚动一个立方体。。。如果你无论如何都不想解析你的纯数据困境,你可以测试这样的东西:

<p>
<p>id<span>5</span></p>
<p>testtext<span>I "am" > than this & < that</span></p>
</p>

当然,你不能把html作为纯文本插入,因为浏览器应该知道该怎么做?只需做一个简单的测试:

var div = $('<div/>').appendTo('body').html('I "am" > than this & < that');
console.log('plainText :', div.text(), ', html :', div.html());
// works as expected...

在将JSON字符串传递给iframe之前,能否对其进行url编码?例如如果将html字符串"<div>'"worky'"</div>"更改为"&lt;div>'"worky'"&lt;/div>",则会正确显示div html。加载iframe时,div元素被写入dom,因此需要防止它正确解析字符串中的html元素。