I helped a friend out by doing a little web work for him. Part of what he needed was an easy way to change a couple pieces of text on his site. Rather than having him edit the HTML I decided to provide an XML file with the messages in it and I used jQuery to pull them out of the file and insert them into the page.
It works great... In Firefox and Chrome, not so great in IE7. I was hoping one of you could tell me why. I did a fair but of googling but couldn't find what I'm looking for.
Here's the 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>
And here's my jQuery call:
<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>
Is there something I need to do differently in IE? Based on the message box with [object Object] I'm assumed that .find was working in IE but since I can't index into the array with [0] or check it's Length I'm guessing that means .find isn't returning any results. Any reason why that would work perfectly in Firefox and Chrome but fail in IE?
I'm a total newbie with jQuery so I hope I haven't just done something stupid. That code above was scraped out of a forum and modified to suit my needs. Since jQuery is cross-platform I figured I wouldn't have to deal with this mess.
Edit: I've found that if I load the page in Visual Studio 2008 and run it then it will work in IE. So it turns out it always works when run through the development web server. Now I'm thinking IE just doesn't like doing .find in XML loaded off of my local drive so maybe when this is on an actual web server it will work OK.
I have confirmed that it works fine when browsed from a web server. Must be a peculiarity with IE. I'm guessing it's because the web server sets the mime type for the xml data file transfer and without that IE doesn't parse the xml correctly.
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 ) ; } },
<!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>
<?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.
Check the content type of the response. If you get messages.xml as the wrong mime type, Internet Explorer won't parse it as XML.
To check the content type, you need access to the XMLHttpRequest object. The normal success callback doesn't pass it as a parameter, so you need to add a generic ajaxComplete or ajaxSuccess event handler. The second parameter for those events is the XMLHttpRequest object. You can call the getResponseHeader method on it to get the content type.
$(document).ajaxComplete(function(e, x) {
alert(x.getResponseHeader("Content-Type"));
});
Unfortunately there's no way that I know of in Internet Explorer to override what the server sends, so if it's wrong you need to change the server to send "text/xml" for the content type.
Some browsers have a overrideMimeType
method that you can call before send
to force it to use "text/xml", but Internet Explorer doesn't support that as far as I know.
The dataType :"xml" does not fix this issue in IE8, rather it throughs a "TypeError" expection.
Quick & Dirty fix, is to wrap the xml response in a html element, like div:
$("<div>" + xml + "</div>").find("something");
(works in all browsers)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With