提问人:Bram Vanroy 提问时间:5/11/2017 最后编辑:CommunityBram Vanroy 更新时间:5/19/2017 访问量:772
我的 HTML 有什么问题,jQuery 没有解析它?
What is wrong with my HTML that jQuery doesn't parse it?
问:
我一直在尝试获取一个 HTML 文件并将其作为 jQuery 对象分配给变量。无济于事。我不确定 Stack Snippets 是否允许 GET 请求,所以这里也是一个 JSFiddle 链接。
var html = '<!DOCTYPE html><html lang="en"><head><title>Template</title></head><body itemscope itemtype="http://schema.org/WebPage"><main><header itemscope itemtype="http://schema.org/Country" itemprop="about"><h1 itemprop="name">Dummy heading</h1><p><span class="capital" title="Capital" itemprop="containsPlace"></span><span title="Dummy title" itemprop="additionalProperty" itemscope itemtype="http://schema.org/PropertyValue"><meta itemprop="name" content="Member of the EU since"><span itemprop="value" class="member-since">Dummy year</span></span></p></header><div itemprop="mainEntity" itemscope itemtype="http://schema.org/ItemList"><meta itemprop="description" content=""><article class="recipe loading" itemprop="itemListElement" itemscope itemtype="http://schema.org/Recipe"><meta itemprop="position" content=""><aside class="media"><div class="img-gallery" itemscope itemtype="http://schema.org/ImageGallery"></div><div itemscope itemtype="http://schema.org/VideoObject" class="youtube"><a itemprop="contentUrl" href="#" title=""><meta itemprop="name" content=""><meta itemprop="uploadDate" content=""><meta itemprop="description" content=""><img itemprop="thumbnailUrl" src="#" alt=""></a><div class="youtube-player"></div></div></aside><div class="text"><div class="wiki-text"><h1 itemprop="name">Dummy heading</h1><p itemprop="description"></p><p class="read-more">For more information about <span class="recipe-name"></span>, read the <a href="#" title="" itemprop="sameAs">Wiki</a>.</p></div><div class="rating" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">Rated <span itemprop="ratingValue">3.5</span>/5 based on <span itemprop="reviewCount">11</span> customer reviews</div><div class="cooking"><h2>Bake it yourself!</h2><div><meta itemprop="cookTime" content=""><span>Bake time: <span class="bake-time"></span></span></div><div class="ingredients-wrapper"><h3>Ingredients <small>for <span itemprop="recipeYield"></span></small></h3><div class="ingredients"><h4>Dummy heading</h4><ul></ul></div></div><div class="how-to"><h3>Steps</h3><ol></ol></div></div></div></article></div></main></body></html>';
$.ajax({
type: 'post',
url: "/echo/html/",
dataType: "html",
data: {
html: html,
delay: 1
}
}).done(function(data) {
// string
console.log(data);
// array
console.log($(data));
// array
console.log($.parseHTML(data));
// array
console.log($($.parseHTML(data)));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
HTML 有效。然而,我无法在对象中得到它。正如预期的那样,返回的数据是一个字符串。但是,当我尝试使用或将其放入jQuery选择器中或将其放入jQuery选择器中,甚至尝试两者时,我总是得到相同的结果:一个包含标题和主要元素的数组。$.parseHTML()
$()
因此,jQuery仍然以某种方式解析它,并创建一个由头部中的元素和正文中的一个元素组成的数组。但为什么呢?我该如何解决这个问题,并将其转换为jQuery对象?我只对身体的内容感兴趣。
有一个类似的问题,但公认的解决方案在进入 JSFiddle 时无济于事,我在 XAMPP 本地也遇到了这个问题。
答:
document.querySelector("body").innerHTML = +
'<object type="text/html" data="'+html+'" ></object>';
...只是工作。所以我本来以为:
let parsedHtml = $('<object />', {
type:'text/html',
data:html
}).html()
也只是工作,但我猜当人们真正将其添加到 DOM 时会发生一些魔术。它解析它,为它构建 CSSOM 和 DOM,并加载所有依赖项,基本上是你期望浏览器对资源做的事情。.html
所以这里有一种方法可以做到这一点:
- 创建一个虚拟占位符,
- 放置里面,
<object>
- 将虚拟人附加到 DOM 中,
- 得到(在它的事件上),
.contents()
<object>
onload
- 并删除假人。
let html = '// your valid html...',
dummyDiv = $('<div />',{
html: '<object type="text/html" data="'+html+'" ></object>',
style:"height:0;overflow:hidden;"
});
$('html').append(dummyDiv);
console.log(dummyDiv.find('object').contents());
注意:Chrome 已经足够智能,可以检测到父级,并且不会加载 <object>
。这就是我使用.您会注意到此元素的内容没有 jQuery 对象的典型结构,因为它是一个文档。你会发现果汁display:none
height:0;overflow:hidden;
dummyDiv.find('object').contents()[1].innerHTML
当 html 字符串已经在变量中时,它会立即加载,但实际上您需要将侦听器放在 并且只运行 4. 和 5. 当侦听器触发时。onload
<object>
评论
jQuery
DOM
.find()
$(data)
.detach()
:-)
将 jQuery.ajax()
选项设置为 。用于将字符串解析为 ; 获得申报; 写入并解析为当前或其他 .processData
false
DOMParser()
html
document
XMLSerizlizer()
DOCTYPE
document.write()
DOCTYPE
document
.documentElement.outerHTML
html
document
processData(默认值:
true
)类型:Boolean
默认情况下,数据作为对象传入到选项中 (从技术上讲,除字符串以外的任何内容)将被处理并 转换为查询字符串,适合默认的 content-type “application/x-www-form-urlencoded”。如果您想发送一个 DOMDocument 或其他未处理的数据,将此选项设置为 。
data
false
我不确定 Stack Snippets 是否允许 GET 请求
是的。可以通过将资源设置为 或表示资源来回显请求,或者 ,请参阅 Stack Overflow 是否在代码片段中有一个“回显页面”来测试 AJAX 请求?GET
url
data URI
Blob URL
$.ajax()
XMLHttpRequest()
fetch()
var html = `<!DOCTYPE html>
<html lang="en">
<head>
<title>Template</title>
</head>
<body itemscope itemtype="http://schema.org/WebPage">
<main>
<header itemscope itemtype="http://schema.org/Country" itemprop="about">
<h1 itemprop="name">Dummy heading</h1>
<p><span class="capital" title="Capital" itemprop="containsPlace"></span><span title="Dummy title" itemprop="additionalProperty" itemscope itemtype="http://schema.org/PropertyValue"><meta itemprop="name" content="Member of the EU since"><span itemprop="value" class="member-since">Dummy year</span></span>
</p>
</header>
<div itemprop="mainEntity" itemscope itemtype="http://schema.org/ItemList">
<meta itemprop="description" content="">
<article class="recipe loading" itemprop="itemListElement" itemscope itemtype="http://schema.org/Recipe">
<meta itemprop="position" content="">
<aside class="media">
<div class="img-gallery" itemscope itemtype="http://schema.org/ImageGallery"></div>
<div itemscope itemtype="http://schema.org/VideoObject" class="youtube">
<a itemprop="contentUrl" href="#" title="">
<meta itemprop="name" content="">
<meta itemprop="uploadDate" content="">
<meta itemprop="description" content=""><img itemprop="thumbnailUrl" src="#" alt=""></a>
<div class="youtube-player"></div>
</div>
</aside>
<div class="text">
<div class="wiki-text">
<h1 itemprop="name">Dummy heading</h1>
<p itemprop="description"></p>
<p class="read-more">For more information about <span class="recipe-name"></span>, read the <a href="#" title="" itemprop="sameAs">Wiki</a>.</p>
</div>
<div class="rating" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">Rated <span itemprop="ratingValue">3.5</span>/5 based on <span itemprop="reviewCount">11</span> customer reviews</div>
<div class="cooking">
<h2>Bake it yourself!</h2>
<div>
<meta itemprop="cookTime" content=""><span>Bake time: <span class="bake-time"></span></span>
</div>
<div class="ingredients-wrapper">
<h3>Ingredients <small>for <span itemprop="recipeYield"></span></small></h3>
<div class="ingredients">
<h4>Dummy heading</h4>
<ul></ul>
</div>
</div>
<div class="how-to">
<h3>Steps</h3>
<ol></ol>
</div>
</div>
</div>
</article>
</div>
</main>
</body>
</html>`;
$.ajax({
type: "GET",
url: "data:text/html," + html,
processData: false
})
.then(function(data) {
// string
console.log(data);
var parser = new DOMParser();
// document
var d = parser.parseFromString(data, "text/html");
// `document`, `document` as jQuery object
console.log(d, $(d));
// get elements having `itemscope` attribute
console.log($(d).find("[itemscope]"));
// do stuff
var dt = new XMLSerializer().serializeToString(d.doctype);
document.write(dt, d.documentElement.outerHTML);
})
.fail(function(jqxhr, textStatus, errorThrown) {
console.log(errorThrown);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
也可以将属性设置为 的 当前 using 元素导入 ,请参阅如何使用 jquery 附加整个 html 文件。html
document
document
<link>
rel
"import"
评论
XMLHttpRequest()
.responseType
"document"
#document
XMLHttpRequest.response
load
readystatechange
fetch()
Response.blob()
html
Blob
dataType:"html"
DOMParser
问题是您正在尝试访问直接html,但实际上它是一个字符串。
因此,您必须渲染 html 才能访问数据。
为此,将响应数据存储到任何 html 元素中并通过它进行访问。
我更改了你的 jsfiddle
,所以你可以看到。
我总是得到相同的结果:一个包含标题和主元素的数组。
问题到底出在哪里?
jQuery仍然解析它,并创建一个由头部中的元素和正文中的一个元素组成的数组。但是为什么?
你期待什么?
这似乎是 parseHtml 的行为。
下面是另一个示例:
$.parseHTML("<div>Hello<span>World</span></div>")
它返回一个包含一个元素的数组:div
如果你看一下 parseHTML 的文档,它说:
将字符串解析为 DOM 节点数组。
所以它似乎正在做它应该做的事情。
我只对身体的内容感兴趣。
正如你所指出的,正文的内容是第二个元素。main
你想用它做什么?
可以通过将 jQuery 对象传递给 jQuery 构造函数来将其包装在 jQuery 对象中。
var html = '<!DOCTYPE html><html lang="en"><head><title>Template</title></head><body itemscope itemtype="http://schema.org/WebPage"><main><header itemscope itemtype="http://schema.org/Country" itemprop="about"><h1 itemprop="name">Dummy heading</h1><p><span class="capital" title="Capital" itemprop="containsPlace"></span><span title="Dummy title" itemprop="additionalProperty" itemscope itemtype="http://schema.org/PropertyValue"><meta itemprop="name" content="Member of the EU since"><span itemprop="value" class="member-since">Dummy year</span></span></p></header><div itemprop="mainEntity" itemscope itemtype="http://schema.org/ItemList"><meta itemprop="description" content=""><article class="recipe loading" itemprop="itemListElement" itemscope itemtype="http://schema.org/Recipe"><meta itemprop="position" content=""><aside class="media"><div class="img-gallery" itemscope itemtype="http://schema.org/ImageGallery"></div><div itemscope itemtype="http://schema.org/VideoObject" class="youtube"><a itemprop="contentUrl" href="#" title=""><meta itemprop="name" content=""><meta itemprop="uploadDate" content=""><meta itemprop="description" content=""><img itemprop="thumbnailUrl" src="#" alt=""></a><div class="youtube-player"></div></div></aside><div class="text"><div class="wiki-text"><h1 itemprop="name">Dummy heading</h1><p itemprop="description"></p><p class="read-more">For more information about <span class="recipe-name"></span>, read the <a href="#" title="" itemprop="sameAs">Wiki</a>.</p></div><div class="rating" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">Rated <span itemprop="ratingValue">3.5</span>/5 based on <span itemprop="reviewCount">11</span> customer reviews</div><div class="cooking"><h2>Bake it yourself!</h2><div><meta itemprop="cookTime" content=""><span>Bake time: <span class="bake-time"></span></span></div><div class="ingredients-wrapper"><h3>Ingredients <small>for <span itemprop="recipeYield"></span></small></h3><div class="ingredients"><h4>Dummy heading</h4><ul></ul></div></div><div class="how-to"><h3>Steps</h3><ol></ol></div></div></div></article></div></main></body></html>';
var parsed = $.parseHTML(html)
var main = parsed[1]
var $main = $(main)
// $main is a jQuery object
console.log("h4 content:", $main.find('h4').text())
评论