37

在 jQuery ajax 调用检索整个 XHTML 文档之后,从结果字符串中选择特定元素的最佳方法是什么?也许有一个库或插件可以解决这个问题?

jQuery 只能选择存在于字符串中的 XHTML 元素,前提是它们通常在 W3C 规范中的 div 中被允许;因此,我对选择 , 和 之类的东西<title><script>好奇<style>

根据 jQuery 文档:

http://docs.jquery.com/Core/jQuery#htmlownerDocument

HTML 字符串不能包含在 div 中无效的元素,例如 html、head、body 或 title 元素。

因此,既然我们已经确定 jQuery 不提供这样做的方法,那么我将如何选择这些元素呢?例如,如果您能告诉我如何选择远程页面的标题,那就太好了!

谢谢,皮特

4

10 回答 10

32

我建议您暂时退出 jQuery 并使用原始 XML dom 方法,而不是破解 jQuery 来执行此操作。使用 XML Dom 方法,您可以这样做:

  window.onload = function(){ 
    $.ajax({
          type: 'GET', 
          url: 'text.html',
          dataType: 'html',
          success: function(data) {

            //cross platform xml object creation from w3schools
            try //Internet Explorer
              {
              xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
              xmlDoc.async="false";
              xmlDoc.loadXML(data);
              }
            catch(e)
              {
              try // Firefox, Mozilla, Opera, etc.
                {
                parser=new DOMParser();
                xmlDoc=parser.parseFromString(data,"text/xml");
                }
              catch(e)
                {
                alert(e.message);
                return;
                }
              }

            alert(xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue);
          }
    });
  }

不要乱用 iframe 等。

于 2009-07-01T15:52:40.763 回答
5

如果您创建一个 iframe 来临时存储文档,这只是一个想法 - 在 FF/Safari 中测试过 - 似乎可行。当然,如果您正在这样做,那么只使用 iframe 的 src 属性来加载文档并在它的“onload”中执行您想要的任何操作可能会更聪明。

  $(function() {
    $.ajax({
      type: 'GET', 
      url: 'result.html',
      dataType: 'html',
      success: function(data) {
        var $frame = $("<iframe src='about:blank'/>").hide();
        $frame.appendTo('body');
        var doc = $frame.get(0).contentWindow.document;
        doc.write(data);
        var $title = $("title", doc);
        alert('Title: '+$title.text() );
        $frame.remove();
      }
    });
  });

我必须将 iframe 附加到正文以使其具有 .contentWindow。

于 2009-06-26T23:38:18.263 回答
3

灵感来自这个答案,但延迟:

function fetchDoc(url) {
  var dfd;
  dfd = $.Deferred();

  $.get(url).done(function (data, textStatus, jqXHR) {

    var $iframe = $('<iframe style="display:none;"/>').appendTo('body');
    var $doc = $iframe.contents();
    var doc = $doc[0];

    $iframe.load(function() {
      dfd.resolveWith(doc, [data, textStatus, jqXHR]);
      return $iframe.remove();
    });
    doc.open();
    doc.write(data);

    return doc.close();
  }).fail(dfd.reject);

  return dfd.promise();
};

并用以下方式吸烟:

fetchDoc('/foo.html').done(function (data, textStatus, jqXHR) {
  alert($('title', this).text());
});

现场演示(点击“运行”)

于 2012-07-08T00:15:46.697 回答
2

一些快速标签重命名怎么样?

$.ajax({
    type : "GET",
    url : 'results.html',
    dataType : "html",
    success: function(data) {

        data = data.replace(/html/g, "xhtmlx");
        data = data.replace(/head/g, "xheadx");
        data = data.replace(/title/g, "xtitlex");
        data = data.replace(/body/g, "xbodyx");

        alert($(data).find("xtitlex").text());
    }

});
于 2009-06-26T14:24:13.743 回答
2

这行得通。我只是拆分了构建块以获得更好的可读性。

检查解释和内联注释以了解其工作原理以及为什么必须这样做。

当然,这不能用于检索跨域内容,因为您要么必须通过自己的脚本代理调用,要么考虑集成类似flXHR(带 Flash 的跨域 Ajax)的东西

调用.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>asd</title>
    <script src="jquery.js" type="text/javascript"></script>
    <script src="xmlDoc.js" type="text/javascript"></script>
    <script src="output.js" type="text/javascript"></script>
    <script src="ready.js" type="text/javascript"></script>
  </head>
  <body>
    <div>
      <input type="button" id="getit" value="GetIt" />
    </div>
  </body>
</html>

jquery.js是(jQuery 1.3.2 未压缩的) test.html一个有效的 XHTML 文档

xmlDoc.js

// helper function to create XMLDocument out of a string
jQuery.createXMLDocument = function( s ) {
  var xmlDoc;
  // is it a IE?
  if ( window.ActiveXObject ) {
    xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
    xmlDoc.async = "false";
    // prevent erros as IE tries to resolve the URL in the DOCTYPE
    xmlDoc.resolveExternals = false;
    xmlDoc.validateOnParse = false;
    xmlDoc.loadXML(s);
  } else {
    // non IE. give me DOMParser
    // theoretically this else branch should never be called
    // but just in case.
    xmlDoc = ( new DOMParser() ).parseFromString( s, "text/xml" );
  }
  return xmlDoc;
};

输出.js

// Output the title of the loaded page
// And get the script-tags and output either the
// src attribute or code
function headerData(data) {
  // give me the head element
  var x = jQuery("head", data).eq(0);
  // output title
  alert(jQuery("title", x).eq(0).text());
  // for all scripttags which include a file out put src
  jQuery("script[src]", x).each(function(index) {
    alert((index+1)+" "+jQuery.attr(this, 'src'));
  });
  // for all scripttags which are inline javascript output code
  jQuery("script:not([src])", x).each(function(index) {
    alert(this.text);
  });
}

准备好了.js

$(document).ready(function() {
  $('#getit').click(function() {
    $.ajax({
      type : "GET",
      url : 'test.html',
      dataType : "xml",
      // overwrite content-type returned by server to ensure
      // the response getst treated as xml
      beforeSend: function(xhr) {
        // IE doesn't support this so check before using
        if (xhr.overrideMimeType) {
          xhr.overrideMimeType('text/xml');
        }
      },
      success: function(data) {
        headerData(data);
      },
      error : function(xhr, textStatus, errorThrown) {
        // if loading the response as xml failed try it manually
        // in theory this should only happen for IE
        // maybe some
        if (textStatus == 'parsererror') {
          var xmlDoc = jQuery.createXMLDocument(xhr.responseText);
          headerData(xmlDoc);
        } else {
          alert("Failed: " + textStatus + " " + errorThrown);
        }
      }
    });
  });
});

createXMLDocument在 Opera 中,没有and功能,整个事情都可以工作beforeSend

Firefox (3.0.11) 和 IE6(无法测试 IE7、IE8、其他浏览器)需要额外的技巧,因为当Content-Type:服务器返回的不是 xml 时,它们会出现问题。我的网络服务器返回Content-Type: text/html; charset=UTF-8test.html.这两个浏览器中,jQuery用说调用error回调。因为在 jQuery.js 的第 3706 行textStatusparsererror

data = xml ? xhr.responseXML : xhr.responseText;

data被设置为空。与 FF 和 IE 一样,它xhr.responseXML为空。发生这种情况是因为他们不知道返回的数据是 xml(就像 Opera 一样)。并且只xhr.responseText设置了整个 xhtml 代码。由于数据为空,第 3708 行

if ( xml && data.documentElement.tagName == "parsererror" )

抛出一个异常,该异常在第 3584 行被捕获并且状态设置为parsererror.

overrideMimeType()在 FF 中,我可以在发送请求之前使用该函数来解决问题。

但是 IE 不支持 XMLHttpRequest 对象上的该函数,因此如果运行错误回调并且错误为parsererror.

test.html 的示例

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Plugins | jQuery Plugins</title>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">var imagePath = '/content/img/so/';</script>
  </head>
  <body>
  </body>
</html>
于 2009-06-28T10:57:17.157 回答
1

无耻地复制并改编自我的另一个答案(简单的 jQuery ajax 示例在返回的 HTML 中找不到元素),这会获取远程页面的 HTML,然后 parseHTML 函数为其创建一个临时 div 元素并将其放入其中,贯穿它,并返回请求的元素。jQuery 然后提醒里面的 text() 。

$(document).ready(function(){
  $('input').click(function(){
    $.ajax({
      type : "POST",
      url : 'ajaxtestload.html',
      dataType : "html",
      success: function(data) {
        alert( data ); // shows whole dom
        var gotcha = parseHTML(data, 'TITLE'); // nodeName property returns uppercase
        if (gotcha) {
          alert($(gotcha).html()); // returns null
        }else{
          alert('Tag not found.');
        }
      },
      error : function() {
        alert("Sorry, The requested property could not be found.");
      }
    });
  });
});

function parseHTML(html, tagName) {
  var root = document.createElement("div");
  root.innerHTML = html;
  // Get all child nodes of root div
  var allChilds = root.childNodes;
  for (var i = 0; i < allChilds.length; i++) {
    if (allChilds[i].nodeName == tagName) {
      return allChilds[i];
    }
  }
  return false;
}

例如,要获取多个项目或脚本标签列表,我认为您必须改进 parseHTML 功能,但是嘿-概念证明:-)

于 2009-06-24T02:10:55.523 回答
0

如果您想查找特定命名字段的值(即表单中的输入),类似这样的内容会为您找到它们:

var fields = ["firstname","surname", ...."foo"];

function findFields(form, fields) {
  var form = $(form);
  fields.forEach(function(field) {
    var val = form.find("[name="+field+"]").val();
    ....
于 2009-06-23T20:58:50.880 回答
0

在将 XML 字符串解析为 之后XML DOM,我要么jQuery直接使用它(你可以通过为选择器提供上下文来做到这一点jQUery,例如$(':title', xdoc.rootElement)或使用XPath(在 Firefox 中工作;据说有 IE 库,但我没有他们取得了很好的成功)。

于 2009-07-01T19:35:10.210 回答
0

这个怎么样:从字符串加载 XML

于 2009-06-24T01:40:19.017 回答
0
$.get('yourpage.html',function(data){
    var content = $('<div/>').append(data).find('#yourelement').html();
});

您也可以简单地临时包裹在一个 div 中。您甚至不需要将它添加到 DOM。

于 2012-09-17T14:19:33.200 回答