web-dev-qa-db-fra.com

jQuery .find () ne renvoie pas de données dans IE mais fait dans Firefox et Chrome

J'ai aidé un ami en faisant un petit travail Web pour lui. Une partie de ce dont il avait besoin était un moyen facile de modifier quelques textes sur son site. Plutôt que de lui demander de modifier le code HTML, j'ai décidé de fournir un fichier XML avec les messages qu'il contient et j'ai utilisé jQuery pour les extraire du fichier et les insérer dans la page.

Cela fonctionne très bien ... Dans Firefox et Chrome, pas si génial dans IE7. J'espérais que l'un de vous pourrait me dire pourquoi. J'ai fait une foire mais googler mais je ne pouvais pas trouver ce que je cherchais.

Voici le XML:

<?xml version="1.0" encoding="utf-8" ?>
<messages>
  <message type="HeaderMessage">
    This message is put up in the header area.
  </message>
  <message type="FooterMessage">
    This message is put in the lower left cell.
  </message>
</messages>

Et voici mon appel jQuery:

<script type="text/javascript">
  $(document).ready(function() {
    $.get('messages.xml', function(d) {
      //I have confirmed that it gets to here in IE
      //and it has the xml loaded.
      //alert(d); gives me a message box with the xml text in it
      //alert($(d).find('message')); gives me "[object Object]"
      //alert($(d).find('message')[0]); gives me "undefined"
      //alert($(d).find('message').Length); gives me "undefined"
      $(d).find('message').each(function() {
        //But it never gets to here in IE
        var $msg = $(this);
        var type = $msg.attr("type");
        var message = $msg.text();
        switch (type) {
        case "HeaderMessage":
          $("#HeaderMessageDiv").html(message);
          break;
        case "FooterMessage":
          $("#footermessagecell").html(message);
          break;
          default:
        }
      });
    });
  });
</script>

Y a-t-il quelque chose que je dois faire différemment dans IE? Basé sur la boîte de message avec [objet Objet], je suppose que .find travaillait dans IE, mais comme je ne peux pas indexer dans le tableau avec [0] ou vérifier sa longueur, je suppose signifie que .find ne renvoie aucun résultat. Une raison pour laquelle cela fonctionnerait parfaitement dans Firefox et Chrome mais échouerait dans IE?

Je suis un débutant avec jQuery, alors j'espère ne pas avoir fait quelque chose de stupide. Le code ci-dessus a été extrait d'un forum et modifié pour répondre à mes besoins. Depuis que jQuery est multi-plateforme, je me suis dit que je n'aurais pas à gérer ce gâchis.

Edit: j'ai constaté que si je charge la page dans Visual Studio 2008 et que je l'exécute, cela fonctionnera dans IE. Il s'avère donc que cela fonctionne toujours lorsqu'il est exécuté via le serveur Web de développement. Maintenant, je pense que IE n'aime simplement pas utiliser. Trouver en XML chargé hors de mon lecteur local, alors peut-être que si cela se trouve sur un serveur Web réel, cela fonctionnera correctement.

J'ai confirmé que cela fonctionne bien lorsque vous naviguez depuis un serveur Web. Doit être une particularité avec IE. J'imagine que c'est parce que le serveur Web définit le type mime pour le transfert du fichier de données XML. Sans cela, IE n'analyse pas correctement le fichier XML.

24
Steve Hiner

Vérifiez le type de contenu de la réponse. Si vous obtenez le type de mime incorrect pour le fichier messages.xml, Internet Explorer ne l’analysera pas au format XML.

Pour vérifier le type de contenu, vous devez accéder à l'objet XMLHttpRequest. Le rappel de réussite normal ne le passe pas en tant que paramètre, vous devez donc ajouter un gestionnaire d'événements générique ajaxComplete ou ajaxSuccess. Le deuxième paramètre de ces événements est l'objet XMLHttpRequest. Vous pouvez appeler la méthode getResponseHeader dessus pour obtenir le type de contenu.

$(document).ajaxComplete(function(e, x) {
    alert(x.getResponseHeader("Content-Type"));
});

Malheureusement, il n’ya aucun moyen, à ma connaissance, dans Internet Explorer de remplacer ce que le serveur envoie. Par conséquent, si vous vous trompez, vous devez changer le serveur afin qu’il envoie "text/xml" pour le type de contenu.

Certains navigateurs ont une méthode overrideMimeType que vous pouvez appeler avant send pour le forcer à utiliser "text/xml", mais Internet Explorer ne la prend pas en charge pour autant que je sache.

12
Matthew Crumley

Since IE's problem is its xml parser chokes on xml files that are not passed down using the correct "text/xml" header, you can include a bit of code in the Ajax complete event:

    complete: function( xhr, status )
    {
      alert( "COMPLETE.  You got:\n\n" + xhr.responseText ) ;
      if( status == 'parsererror' )
      {
        alert( "There was a PARSERERROR.  Luckily, we know how to fix that.\n\n" +
               "The complete server response text was " + xhr.responseText ) ;

        xmlDoc = null;

        // Create the xml document from the responseText string.
        // This uses the w3schools method.
        // see also
        if( window.DOMParser )
        {
          parser=new DOMParser();
          xmlDoc=parser.parseFromString( xhr.responseText,"text/xml" ) ;
        }
        else // Internet Explorer
        {
          xmlDoc=new ActiveXObject( "Microsoft.XMLDOM" ) ;
          xmlDoc.async = "false" ;
          xmlDoc.loadXML( xhr.responseText ) ;
        }

        $( '#response' ).append( '<p>complete event/xmlDoc: ' + xmlDoc + '</p>' ) ;
        $( '#response' ).append( '<p>complete event/status: ' + status + '</p>' ) ;

        processXMLDoc( xmlDoc ) ;
      }
    },

here's a more complete example

<!DOCTYPE html>
<html>
<head>
<title>Reading XML with jQuery</title>
<style>
#response
{
  border: solid 1px black;
  padding: 5px;
}
</style>
<script src="jquery-1.3.2.min.js"></script>
<script>
function processXMLDoc( xmlDoc )
{
  var heading = $(xmlDoc).find('heading').text() ;
  $( '#response' ).append( '<h1>' + heading + '</h1>' ) ;

  var bodyText = $(xmlDoc).find('body').text() ;
  $( '#response' ).append( '<p>' + bodyText + '</p>' ) ;
}
$(document).ready(function()
{
  jQuery.ajax({

    type: "GET",

    url: "a.xml",  // ! watch out for same
    // origin type problems

    dataType: "xml", // 'xml' passes it through the browser's xml parser

    success: function( xmlDoc, status )
    {
      // The SUCCESS EVENT means that the xml document
      // came down from the server AND got parsed successfully
      // using the browser's own xml parsing caps.

      processXMLDoc( xmlDoc );

      // IE gets very upset when
      // the mime-type of the document that
      // gets passed down isn't text/xml.

      // If you are missing the text/xml header
      // apparently the xml parse fails,
      // and in IE you don't get to execute this function AT ALL.

    },
    complete: function( xhr, status )
    {
      alert( "COMPLETE.  You got:\n\n" + xhr.responseText ) ;
      if( status == 'parsererror' )
      {
        alert( "There was a PARSERERROR.  Luckily, we know how to fix that.\n\n" +
               "The complete server response text was " + xhr.responseText ) ;

        xmlDoc = null;

        // Create the xml document from the responseText string.
        // This uses the w3schools method.
        // see also
        if( window.DOMParser )
        {
          parser=new DOMParser();
          xmlDoc=parser.parseFromString( xhr.responseText,"text/xml" ) ;
        }
        else // Internet Explorer
        {
          xmlDoc=new ActiveXObject( "Microsoft.XMLDOM" ) ;
          xmlDoc.async = "false" ;
          xmlDoc.loadXML( xhr.responseText ) ;
        }

        $( '#response' ).append( '<p>complete event/xmlDoc: ' + xmlDoc + '</p>' ) ;
        $( '#response' ).append( '<p>complete event/status: ' + status + '</p>' ) ;

        processXMLDoc( xmlDoc ) ;
      }
    },
    error: function( xhr, status, error )
    {
      alert( 'ERROR: ' + status ) ;
      alert( xhr.responseText ) ;
    }
  });
});
</script>
</head>
<body>
  <div>
    <h1><a href="http://think2loud.com/reading-xml-with-jquery/">Reading XML with jQuery</a></h1>
    <p>
      <a href="http://docs.jquery.com/Ajax/jQuery.ajax#options">#1 jQuery.ajax ref</a>
    </p>

  </div>

  <p>Server says:</p>
  <pre id="response">

  </pre>
</body>
</html>

contents of a.xml

<?xml version="1.0"?>
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

It extends this example.

19
bobobobo

Le type de données: "xml" ne résout pas ce problème dans IE8, mais une expection "TypeError".

Quick & Dirty, consiste à envelopper la réponse XML dans un élément HTML, comme div:

$("<div>" + xml + "</div>").find("something");

(fonctionne dans tous les navigateurs)

6
McMadsen

Vous constaterez peut-être que si vous transmettez le type de données à votre appel get, celui-ci peut être analysé correctement au format XML. Les bizarreries d'Internet Explorer pourraient empêcher jQuery de la détecter automatiquement en tant que XML, ce qui entraînerait le transfert du type de données incorrect à la fonction de rappel.

<script type="text/javascript">
      $(document).ready(function() {
        $.get('messages.xml', function(d) {
          //I have confirmed that it gets to here in IE
          //and it has the xml loaded.
          //alert(d); gives me a message box with the xml text in it
          //alert($(d).find('message')); gives me "[object Object]"
          //alert($(d).find('message')[0]); gives me "undefined"
          //alert($(d).find('message').Length); gives me "undefined"
          $(d).find('message').each(function() {
            //But it never gets to here in IE
            var $msg = $(this);
            var type = $msg.attr("type");
            var message = $msg.text();
            switch (type) {
            case "HeaderMessage":
              $("#HeaderMessageDiv").html(message);
              break;
            case "FooterMessage":
              $("#footermessagecell").html(message);
              break;
              default:
            }
          });
        }, "xml");
      });
</script>

MODIFIER:

En fait, je viens juste de constater que .find () ne fonctionne pour un projet dans aucun navigateur, mais j’ai pu utiliser .filter () à la place. C'est embêtant de devoir recourir à cela, mais si cela fonctionne ...

$(d).filter('message').each(......);
5
MJJames

J'ai également eu le même problème mais j'avais résolu le problème IE jQuery XML .find () en utilisant le code ci-dessous.

Remarque: Utilisez .text () au lieu de .html ().

jQuery.ajax({
 type: "GET",
        url: "textxml.php",
        success: function(msg){             
            data = parseXml(msg);
            //alert(data);
            var final_price = jQuery(data).find("price1").text();
            alert(final_price); 
            }
    });     

function parseXml(xml) {
     if (jQuery.browser.msie) {
        var xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); 
        xmlDoc.loadXML(xml);
        xml = xmlDoc;
    }   
    return xml;
}
3
sanjeev

Tu peux faire 

<a>
<messages>
  <message type="HeaderMessage">
    This message is put up in the header area.
  </message>
  <message type="FooterMessage">
    This message is put in the lower left cell.
  </message>
</messages>
</a>

et utilisez find (). Cela fonctionne pour IE8 et pour Firefox v.3.6.3

3
Guest

J'ai rencontré le même problème lorsque je récupérais des données d'un document XML. Après avoir beaucoup cherché sur Internet, je suis arrivé à la recherche de ce site Web, mais sans réponse appropriée. Mais une réponse m'a aidé à résoudre le problème cependant:

"Etant donné que le problème rencontré par IE est que son analyseur XML coupe les fichiers xml qui ne sont pas transmis à l'aide du bon en-tête" text/xml ", vous pouvez inclure un peu de code dans l'événement complet Ajax:"

J'ai identifié deux problèmes avec IE lors des appels $ .ajax (...) et $ .get (...):

  1. La valeur du paramètre xml doit être en majuscule ('XML' et non 'xml') pour les deux appels - $ .ajax (..., dataType: "XML") et $ .get ( xmlDataFilePath, fonction (d) {...}, "xml")

  2. Lorsque l'appel ajax aboutit, l'argument XML de la fonction de rappel est en fait un string et non un objet XML DOM

Le deuxième problème est résolu de cette façon:

$(document).ready(function()
{
    $.ajax(
    { 
        type: "GET",
        url: "messages.xml", 
        dataType: "XML", /* this parameter MUST BE UPPER CASE for it to work in IE */
        success: function(xml)
        { 
            processXmlDoc( createXmlDOMObject ( xml ) );
        }, /* success: */
        error: function(xhr, textStatus, errorThrown)
        { 
            alert(textStatus + ' ' + errorThrown);
        } /* error: */
    });/* $.ajax */

    function createXmlDOMObject(xmlString)
    {
        var xmlDoc = null;

        if( ! window.DOMParser )
        {
            // the xml string cannot be directly manipulated by browsers 
            // such as Internet Explorer because they rely on an external 
            // DOM parsing framework...
            // create and load an XML document object through the DOM 
            // ActiveXObject that it can deal with
            xmlDoc = new ActiveXObject( "Microsoft.XMLDOM" );
            xmlDoc.async = false;
            xmlDoc.loadXML( xmlString );
        }
        else
        {
            // the current browser is capable of creating its own DOM parser
            parser = new DOMParser();
            xmlDoc = parser.parseFromString( xmlString, "text/xml" ) ;
        }

        return xmlDoc;
    }

    function processXmlDoc(xmlDoc)
    {
        // write here your XML processing logic for the document object...
    } 
}); // $(document).ready
1
Bigabdoul

J'ai également eu le même problème lors de l'importation des contacts de messagerie. J'ai pu importer des contacts et les afficher dans tous les navigateurs, à l'exception de IE, car .find() ne fonctionnait pas.

Donc, j'ai assigné "text/xml" à response.contentType

c'est-à-dire response.contentType = "text/xml" et cela a fonctionné.

auparavant c'était "text/html"

1
Wasim
$.ajax({
  url: 'messages.xml',
  success: function(data){
     $(d).find('message').each(function(){
        //But it never gets to here in IE
        var $msg = $(this);
        var type = $msg.attr("type");
        var message = $msg.text();
        switch (type) {
          case "HeaderMessage":
             $("#HeaderMessageDiv").html(message);
          break;
          case "FooterMessage":
             $("#footermessagecell").html(message);
          break;
        }
      });
  },
  dataType: 'xml'
});

Essayez de dire à jQuery quel type de données il obtient pour qu’il utilise les bonnes méthodes pour traiter votre demande.

1
RobertPitt

Parfois, IE lit les sauts de ligne en tant que nœuds supplémentaires. Essayez de supprimer l’espace blanc qui reste jusqu’aux balises ou de l’envelopper en tant que CDATA. 

1
jacobangel

Changer le contenu suivant.

dataType :"text/xml",

à

dataType :"xml",

Pas besoin de changer la recherche ().

1
Rahul Vaidya

Si le XML est généré par un script PHP, vous pouvez le faire.

<?php
    header("Content-type: text/xml");
    echo '<myxml></myxml>';
?>

Ensuite, la méthode find fonctionne sur tous les navigateurs

0
christophe

J'ai le même problème...

Résolu avec ceci:

http://www.w3schools.com/dom/dom_parser.asp

if (window.DOMParser)
  {
  parser=new DOMParser();
  xmlDoc=parser.parseFromString(text,"text/xml");
  }
else // Internet Explorer
  {
  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
  xmlDoc.async="false";
  xmlDoc.loadXML(text); 
  }

utilisez-le pour transformer votre objet var en xml ...

0
stevensf

Cela fonctionne bien !!! Essaye ça,

Chrome/Firefox:

xml.children[0].childNodes[1].innerHTML;

IE8 +/Safari:

xml.childNodes[0].childNodes[1].textContent;

IE8:

xml.documentElement.childNodes[1].text;

Exemple de code ici,

var xml = $.parseXML(XMLDOC); 

Var xmlNodeValue = ""; 

if(userAgent.match("msie 8.0")){

xmlNodeValue = xml.children[0].childNodes[1].innerHTML;

}else{ // IE8+

xmlNodeValue = xml.childNodes[0].childNodes[1].textContent; 

}
0
Muthu Selvam

J'ai eu le même problème, je développe une application qui est basée sur le Web, mais j'en ai besoin pour la déployer hors ligne, sur un CD. J'ai trouvé la solution dans cette page qui est la même solution que vous pouvez voir ci-dessus http://docs.jquery.com/Specifying_the_Data_Type_for_AJAX_Requests Et le code est très simple:

 $.ajax({
   url: "data.xml",
   dataType: ($.browser.msie) ? "text" : "xml",
   success: function(data){
     var xml;
     if (typeof data == "string") {
       xml = new ActiveXObject("Microsoft.XMLDOM");
       xml.async = false;
       xml.loadXML(data);
     } else {
       xml = data;
     }
     // write here your XML processing logic for the document object... 
   }
 });
0
prof. Xavier