23

我正在做一个 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');
});

问题是当我改变abody我什么也得不到(没有错误,只是没有 html)。我假设body是一个标签,就像'a'一样?我究竟做错了什么?

所以这对我有用:

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

但这不会:

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

5 回答 5

13

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

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

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

(带有 xml 解析的解决方案会更好,但是对于无效的 XML 响应,您必须进行一些“字符串解析”。)

于 2016-02-02T15:44:31.690 回答
12

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

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

文档中的相关引用:

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

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

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

于 2013-01-20T09:39:27.293 回答
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 是获取window.documentiFrame 元素的符合标准的方式,但当然 IE 并不真正关心标准,所以这是如何以window.document.body跨平台方式获取对 iFrame 对象的引用.. .

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

于 2013-01-20T10:00:53.310 回答
4

我想出了一些很棒的东西(我想!)

得到你的 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 解析器崩溃。

于 2014-05-26T19:41:31.400 回答
1

对我有用的正则表达式解决方案:

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

详解:https ://regex101.com/r/kFkNeI/1

于 2019-08-11T12:00:36.763 回答