在ajax HTML响应中查找body标签

时间:2013-01-20 09:34:22

标签: javascript jquery ajax document-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');
});

问题在于,当我在a中更改body时,我什么都没得到(没有错误,只是没有HTML)。我假设身体是一个标签,就像' a'是什么?我做错了什么?

所以这对我有用:

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

但这并不是:

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

5 个答案:

答案 0 :(得分:11)

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

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

也适用于 head 或任何其他标记

(使用xml解析的解决方案会更好但是使用无效的XML响应你必须做一些&#34;字符串解析&#34;。)

答案 1 :(得分:9)

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

原因是返回的datastring(尝试console.log(typeof(data)))。现在,根据the jQuery documentation,当从包含复杂HTML标记的字符串创建jQuery对象时,body等标记可能会被剥离。发生这种情况是因为为了创建对象,HTML标记实际上插入到DOM中,不允许这样的附加标记。

the documentation的相关引用:

  

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

     

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

     

传递复杂的HTML时,某些浏览器可能无法生成DOM   它完全复制了提供的HTML源代码。如上所述,jQuery   使用浏览器的.innerHTML属性来解析传递的HTML和   将其插入当前文档。在这个过程中,一些   浏览器过滤掉某些元素,例如&lt; html&gt;,&lt;标题&gt;,或   &LT;头&gt;元素。结果,插入的元素可能不是   传递原始字符串的代表。

答案 2 :(得分:6)

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

$.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 = $('<iframe id="frame" src="/" style="display: none;"></iframe>').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]

请参阅:contentDocument for an iframe

答案 3 :(得分:5)

我想出了一些奇妙的东西(我想!)

你的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响应的一个共同特征可能是<!DOCTYPE>标记,这会使文档在这种意义上无效。在使用此方法之前,可能需要删除<!DOCTYPE>个标记!另请注意<!--[if IE 8]>...<![endif]-->等功能,不带标签的标签,例如:

<ul>
    <li>content...
    <li>content...
    <li>content...
</ul>

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

答案 4 :(得分:0)

最适合我的正则表达式解决方案:

var head = res.match(/<head.*?>.*?<\/head.*?>/s);
var body = res.match(/<body.*?>.*?<\/body.*?>/s);

详细说明:https://regex101.com/r/kFkNeI/1