Javascript 在 ajax HTML 响应中查找 body 标签
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14423257/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find body tag in an ajax HTML response
提问by Youss
I'm making an ajax call to fetch content and append this content like this:
我正在调用 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');
});
The problem is that when I change ain bodyI get nothing (no error, just no html). Im assuming body is a tag just like 'a' is? What am I doing wrong?
问题是,当我更改时a,body我什么也没得到(没有错误,只是没有 html)。我假设 body 是一个标签,就像 'a' 一样?我究竟做错了什么?
So this works for me:
所以这对我有用:
mas = $(data).find('a');
But this doesn't:
但这不会:
mas = $(data).find('body');
采纳答案by Boaz - Reinstate Monica
Parsing the returned HTML through a jQuery object (i.e $(data)) in order to get the bodytag is doomed to fail, I'm afraid.
通过 jQuery 对象(即$(data))解析返回的 HTML以获取body标签注定会失败,恐怕。
The reason is that the returned datais a string(try console.log(typeof(data))). Now, according to the jQuery documentation, when creating a jQuery object from a string containing complex HTML markup, tags such as bodyare likely to get stripped. This happens since in order to create the object, the HTML markup is actually inserted into the DOM which cannot allow such additional tags.
原因是返回的data是一个string(try console.log(typeof(data)))。现在,根据jQuery 文档,当从包含复杂 HTML 标记的字符串创建 jQuery 对象时,诸如此类的标记body可能会被剥离。发生这种情况是因为为了创建对象,HTML 标记实际上被插入到 DOM 中,而 DOM 不允许此类附加标签。
Relevant quote from the documentation:
文档中的相关引用:
If a string is passed as the parameter to $(), jQuery examines the string to see if it looks like HTML.
[...] If the HTML is more complex than a single tag without attributes, as it is in the above example, the actual creation of the elements is handled by the browser's innerHTML mechanism. In most cases, jQuery creates a new element and sets the innerHTML property of the element to the HTML snippet that was passed in. When the parameter has a single tag (with optional closing tag or quick-closing) — $( "< img / >" ) or $( "< img >" ), $( "< a >< /a >" ) or $( "< a >" ) — jQuery creates the element using the native JavaScript createElement() function.
When passing in complex HTML, some browsers may not generate a DOM that exactly replicates the HTML source provided. As mentioned, jQuery uses the browser"s .innerHTML property to parse the passed HTML and insert it into the current document. During this process, some browsers filter out certain elements such as < html >, < title >, or < head > elements. As a result, the elements inserted may not be representative of the original string passed.
如果将字符串作为参数传递给 $(),jQuery 会检查该字符串以查看它是否看起来像 HTML。
[...] 如果 HTML 比没有属性的单个标签更复杂,就像在上面的例子中那样,元素的实际创建是由浏览器的 innerHTML 机制处理的。在大多数情况下,jQuery 会创建一个新元素并将该元素的 innerHTML 属性设置为传入的 HTML 片段。当参数具有单个标签时(带有可选的结束标签或快速结束标签)—— $( "< img / >" ) 或 $( "< img >" )、$( "< a ></a >" ) 或 $( "< a >" ) — jQuery 使用原生 JavaScript createElement() 函数创建元素。
在传递复杂的 HTML 时,某些浏览器可能无法生成与所提供的 HTML 源代码完全相同的 DOM。如前所述,jQuery 使用浏览器的 .innerHTML 属性来解析传入的 HTML 并将其插入到当前文档中。在此过程中,一些浏览器会过滤掉某些元素,例如 <html>、<title> 或 <head> 元素. 结果,插入的元素可能不代表传递的原始字符串。
回答by Yush0
I ended up with this simple solution:
我最终得到了这个简单的解决方案:
var body = data.substring(data.indexOf("<body>")+6,data.indexOf("</body>"));
$('body').html(body);
Works also with heador any other tag.
也适用于head或任何其他标签。
(A solution with xml parsing would be nicer but with an invalid XML response you have to do some "string parsing".)
(使用 xml 解析的解决方案会更好,但是对于无效的 XML 响应,您必须进行一些“字符串解析”。)
回答by Billy Moon
I experimented a little, and have identified the cause to a point, so pending a real answer which I would be interested in, here is a hack to help understand the issue
我进行了一些实验,并确定了某个原因,因此在等待我感兴趣的真正答案之前,这里有一个 hack 来帮助理解这个问题
$.get('/',function(d){
// replace the `HTML` tags with `NOTHTML` tags
// and the `BODY` tags with `NOTBODY` tags
d = d.replace(/(<\/?)html( .+?)?>/gi,'NOTHTML>',d)
d = d.replace(/(<\/?)body( .+?)?>/gi,'NOTBODY>',d)
// select the `notbody` tag and log for testing
console.log($(d).find('notbody').html())
})
Edit: further experimentation
编辑:进一步实验
It seems it is possible if you load the content into an iframe, then you can access the frame content through some dom object hierarchy...
如果您将内容加载到 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()
})
})
Edit: more research
编辑:更多研究
It seems that contentDocument is the standards compliant way to get hold of the window.documentelement of an iFrame, but of course IE don't really care for standards, so this is how to get a reference to the iFrame's window.document.bodyobject in a cross platform way...
似乎 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]
回答by Gershom
I FIGURED OUT SOMETHING WONDERFUL (I think!)
我发现了一些很棒的东西(我认为!)
Got your html as a string?
把你的 html 作为一个字符串?
var results = //probably an ajax response
Here's a jquery object that will work exactly like the elements currently attached to the DOM:
这是一个 jquery 对象,它的工作方式与当前附加到 DOM 的元素完全一样:
var superConvenient = $($.parseXML(response)).children('html');
Nothing will be stripped from superConvenient! You can do stuff like superConvenient.find('body')or even
什么都不会被剥夺superConvenient!你可以做类似的事情superConvenient.find('body'),甚至
superConvenient.find('head > script');
superConvenientworks exactly like the jquery elements everyone is used to!!!!
superConvenient就像每个人都习惯的 jquery 元素一样工作!!!!
NOTE
笔记
In this case the string resultsneeds to be valid XMLbecause it is fed to JQuery's parseXMLmethod. A common feature of an HTML response may be a <!DOCTYPE>tag, which would invalidate the document in this sense. <!DOCTYPE>tags may need to be stripped before using this approach! Also watch out for features such as <!--[if IE 8]>...<![endif]-->, tags without closing tags, e.g.:
在这种情况下,字符串results需要是有效的 XML,因为它被提供给 JQuery 的parseXML方法。HTML 响应的一个共同特征可能是一个<!DOCTYPE>标签,从这个意义上说,它会使文档无效。<!DOCTYPE>在使用这种方法之前可能需要剥离标签!还要注意<!--[if IE 8]>...<![endif]-->没有关闭标签的标签等功能,例如:
<ul>
<li>content...
<li>content...
<li>content...
</ul>
... and any other features of HTML that will be interpreted leniently by browsers, but will crash the XML parser.
... 以及任何其他 HTML 特性,这些特性将被浏览器轻松解释,但会使 XML 解析器崩溃。
回答by Noel Schenk
Regex solution that worked for me:
对我有用的正则表达式解决方案:
var head = res.match(/<head.*?>.*?<\/head.*?>/s);
var body = res.match(/<body.*?>.*?<\/body.*?>/s);
Detailed explanation: https://regex101.com/r/kFkNeI/1

