What is the best practice for parsing remote content with jQuery?

前端 未结 10 1579
时光说笑
时光说笑 2020-11-27 03:21

Following a jQuery ajax call to retrieve an entire XHTML document, what is the best way to select specific elements from the resulting string? Perhaps there is a library or

10条回答
  •  爱一瞬间的悲伤
    2020-11-27 03:47

    This works. I just split up the building blocks for better readability.

    Check the explanation and the inline comments to grasp the workings of this and why it has to be made like this.

    Of course this can't be used to retrieve cross-domain-content for that you either have to proxy the calls through a script of yours or think about integration something like flXHR (Cross-Domain Ajax with Flash)

    call.html

    
    
      
        
        asd
        
        
        
        
      
      
        

    jquery.js is (jQuery 1.3.2 uncompressed) test.html a valid XHTML-Document

    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;
    };
    

    output.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);
      });
    }
    

    ready.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);
            }
          }
        });
      });
    });
    

    In Opera the whole thing works without the createXMLDocument and the beforeSend function.

    The extra trickery is needed for Firefox (3.0.11) and IE6 (can't test IE7, IE8, other browsers) as they have a problem when the Content-Type: returned by the server doesn't indicate that it's xml. My webserver returned Content-Type: text/html; charset=UTF-8 for test.html. In those two browsers jQuery called the error callback with textStatus saying parsererror. Because in line 3706 in jQuery.js

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

    data is being set to null. As in FF and IE the xhr.responseXML is null. This happens because they don't get that the returned data is xml (as Opera does). And only xhr.responseText is set with the whole xhtml-code. As data is null the line 3708

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

    throws an exception which is catched in line 3584 and status is set to parsererror.

    In FF I can solve the problem by using the overrideMimeType() function before sending the request.

    But IE doesn't support that function on the XMLHttpRequest-object so I have to generate the XMLDocument myself if the error-callback is run and the error is parsererror.

    example for test.html

    
    
    
      
        
        Plugins | jQuery Plugins
        
        
      
      
      
    
    

提交回复
热议问题