2017-05-10 110 views
3

我一直在试图获取一个HTML文件,并将其作为一个jQuery对象分配给一个变量。无济于事。我不确定Stack Snippets是否允许GET请求,所以这里也是JSFiddle link我的HTML有什么问题,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>'; 
 
    
 
    $.ajax({ 
 
     type: 'post', 
 
     url: "/echo/html/", 
 
     dataType: "html", 
 
     data: { 
 
     html: html, 
 
     delay: 1 
 
     } 
 
    }).done(function(data) { 
 
     // string 
 
    \t 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是有效的。然而,我不能把它放在一个物体上。正如所料,返回的数据是一个字符串。但是,当我尝试使用$.parseHTML()将该字符串解析为HTML或将其放入jQuery选择器$()甚至尝试使用这两个字符串时,我总是得到相同的结果:包含标题和主元素的数组。

因此,一些如何jQuery仍然解析它,并使元素在头部和身体的一个元素的数组。但是为什么?我该如何弥补这一点,并将其转换为jQuery对象?我只对身体的内容感兴趣。

a similar question,但接受的解决方案并没有帮助,因为它进入了JSFiddle,我也在XAMPP本地遇到这个问题。

回答

2
document.querySelector("body").innerHTML = + 
    '<object type="text/html" data="'+html+'" ></object>'; 

...只是工作。所以我预料:

let parsedHtml = $('<object />', { 
    type:'text/html', 
    data:html 
}).html() 

也只是工作,但我猜一些奇迹发生了,当一个真正把它添加到DOM。它解析它,为它构建CSSOM和DOM,并加载所有依赖项,基本上你期望浏览器使用.html资源。

所以这里有一个办法做到这一点:

  1. 创建一个虚拟占位符,
  2. 地方<object>内,
  3. 追加假人DOM,
  4. 得到<object>.contents()(它是onload事件),
  5. 并删除虚拟。
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已经是足够聪明来检测一个父一个display:none无法加载<object>。这就是我使用height:0;overflow:hidden;的原因。你会注意到这个元素的内容没有jQuery对象的典型结构,因为它是一个文档。你会发现在

dummyDiv.find('object').contents()[1].innerHTML 

汁当HTML字串已经是一个变量,它加载迅速,但在现实中你需要放置在<object>onload监听器,并只运行4.当侦听器触发时5.

+0

嗯,有没有什么办法可以做到这一点,而无需首先将元素添加到DOM?问题是我想将内容加载到内存中,对其进行一些修改(克隆,分离,整个交易),然后将其添加到DOM。在内存中,因为这应该比做DOM修改更快。 –

+0

不是我所知道的。事情就是这样被正确解析。否则,你可以在你的字符串上运行一些'jQuery'技巧,但它不是'DOM'元素,所以并不是所有的东西都可用。例如,对'$(data)'运行'.find()'并按类选择将会工作,而选择标记不会,因为它不是DOM。这是一个字符串。通过上述方法,您不仅可以等待加载ajax,还可以正确加载生成的DOM(以防万一它具有一些DOM操作脚本)。 –

+0

我明白了。聪明。所以,最好的想法可能是将它附加到html/body,然后在VAR中执行'.detach()',将解析的内容有效地放回到内存中,删除虚拟对象。操作VAR,并将VAR添加回DOM? –

1

Set jQuery.ajax()processData option to false。使用DOMParser()解析字符串为htmldocument; XMLSerizlizer()得到DOCTYPE声明; document.write()编写DOCTYPE并解析document.documentElement.outerHTML到当前或其他htmldocument

过程数据(默认:true

类型:Boolean

默认情况下,传递到data选项作为对象数据 (从技术上讲,任何字符串以外的)会处理并且 转换成查询字符串,适合默认内容类型 “application/x-www-form-urlencoded”。如果要发送一个 DOMDocument或其他未处理的数据,请将此选项设置为false


我不知道,如果堆栈片段允许GET请求

是。有可能通过在$.ajax()XMLHttpRequest()fetch()设置资源的urldata URIBlob URL表示回声GET请求,请参见Does Stack Overflow have an “echo page” to test AJAX requests, inside a code snippet?

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>

另外,也可以导入一个htmldocument到当前document使用<link>元素rel属性设置为"import",请参阅How to append a whole html file with jquery

+0

你也可以使用'XMLHttpRequest()','.responseType'设置为''document'''在'load'或'readystatechange'事件中获得'#document'作为'XMLHttpRequest.response',或者'fetch()','Response.blob()'把'html'变成'Blob'。 – guest271314

+0

使用dataType:html有什么区别?这不是它应该做什么?将检索到的内容处理为html? –

+0

使用'dataType:“html”'返回相同的结果。 – guest271314

0

问题是你正在尝试访问直接的HTML,但实际上是一个字符串。

所以你必须呈现html来访问数据。

用于存储响应数据到任何html元素并通过它访问。

我改变了你的jsfiddle,所以你可以看到。

0

我总是得到相同的结果:包含标题和主要元素的数组。

究竟是什么问题?

jQuery仍然解析它,并在头部和身体中的一个元素作出一个数组。但为什么?

你在期待什么?

这似乎是parseHtml的行为。

再举一例:

$.parseHTML("<div>Hello<span>World</span></div>") 

它返回一个元素的数组:div

如果你看看docs for parseHTML它说:

解析字符串转换成数组DOM节点。

所以它似乎在做它应该做的。

我只对身体的内容感兴趣。

正文的内容是main正如你所指出的是第二个元素。

你想用它做什么?

你可以通过将它传递给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())