在ajax HTML响应中查找body标签

我正在进行ajax调用以获取内容并附加此内容,如下所示:

$(function(){ var site = $('input').val(); $.get('file.php', { site:site }, function(data){ mas = $(data).find('a'); mas.map(function(elem, index) { divs = $(this).html(); $('#result').append('' + divs + ''); }) }, 'html'); }); 

问题是,当我改变body我什么也得不到(没有错误,只有没有HTML)。 我假设身体是一个像’a’的标签? 我究竟做错了什么?

所以这对我有用:

  mas = $(data).find('a'); 

但这不是:

  mas = $(data).find('body'); 

通过jQuery对象解析返回的HTML(即$(data) )以获取body标签注定要失败,我担心。

原因是返回的data是一个string (尝试console.log(typeof(data)) )。 现在,根据jQuery文档 ,当从包含复杂HTML标记的字符串创建jQuery对象时,诸如body类的标记可能会被剥离。 这是因为为了创建对象,HTML标记实际上插入到DOM中,这不允许这样的附加标记。

文件中的相关引用:

如果将字符串作为参数传递给$(),jQuery将检查字符串以查看它是否看起来像HTML。

[…]如果HTML比没有属性的单个标签更复杂,就像在上面的例子中那样,元素的实际创建由浏览器的innerHTML机制处理。 在大多数情况下,jQuery会创建一个新元素,并将元素的innerHTML属性设置为传入的HTML片段。当参数有一个标记(带有可选的结束标记或快速关闭)时 – $(““)或$(”“),$(” “)或$(”“) – jQuery使用本机JavaScript createElement()函数创建元素。

传递复杂的HTML时,某些浏览器可能无法生成完全复制所提供的HTML源的DOM。 如上所述,jQuery使用浏览器的.innerHTML属性来解析传递的HTML并将其插入到当前文档中。在此过程中,某些浏览器会过滤掉某些元素,例如,或<head>元素结果,插入的元素可能无法代表传递的原始字符串。 </head>

我最终得到了这个简单的解决方案:

 var body = data.substring(data.indexOf("")+6,data.indexOf("")); $('body').html(body); 

也适用于头部或任何其他标签

(使用xml解析的解决方案会更好但是如果XML响应无效,则必须执行一些“字符串解析”。)

我做了一点实验,并确定了原因,所以等待我真正感兴趣的答案,这是一个帮助理解问题的黑客

 $.get('/',function(d){ // replace the `HTML` tags with `NOTHTML` tags // and the `BODY` tags with `NOTBODY` tags d = d.replace(/(<\/?)html( .+?)?>/gi,'$1NOTHTML$2>',d) d = d.replace(/(<\/?)body( .+?)?>/gi,'$1NOTBODY$2>',d) // select the `notbody` tag and log for testing console.log($(d).find('notbody').html()) }) 

编辑:进一步的实验

看起来有可能将内容加载到iframe中,然后您可以通过某个dom对象层次结构访问帧内容…

 // get a page using AJAX $.get('/',function(d){ // create a temporary `iframe`, make it hidden, and attach to the DOM var frame = $('').appendTo('body') // check that the frame has loaded content $(frame).load(function(){ // grab the HTML from the body, using the raw DOM node (frame[0]) // and more specifically, it's `contentDocument` property var html = $('body',frame[0].contentDocument).html() // check the HTML console.log(html) // remove the temporary iframe $("#frame").remove() }) }) 

编辑:更多研究

似乎contentDocument是获取iFrame的window.document元素的标准兼容方式,但当然IE并不真正关心标准,所以这是如何获取对iFrame的window.document.body的引用。跨平台方式的对象……

 var iframeDoc = iframe.contentDocument || iframe.contentWindow.document; var iframeBody = iframeDoc.body; // or for extra caution, to support even more obsolete browsers // var iframeBody = iframeDoc.getElementsByTagName("body")[0] 

请参阅: iframe的contentDocument

我想出了很棒的事情(我想!)

得到你的HTML作为字符串?

 var results = //probably an ajax response 

这是一个jquery对象,它的工作方式与当前附加到DOM的元素完全相同:

 var superConvenient = $($.parseXML(response)).children('html'); 

什么都不会从superConvenient剥离出来! 你可以做一些像superConvenient.find('body')甚至是

 superConvenient.find('head > script'); 

superConvenient工作原理与每个人习惯的jquery元素完全相同!

注意

在这种情况下,字符串results需要是有效的XML,因为它被提供给JQuery的parseXML方法。 HTML响应的一个共同特征可能是标记,这会使文档在这种意义上无效。 在使用此方法之前,可能需要剥离标记! 还要注意 ,标签没有关闭标签,例如:

 
  • content...
  • content...
  • content...

…以及浏览器将宽大地解释HTML的任何其他function,但会破坏XML解析器。