PDA

View Full Version : Parsing data from an xml file



bigalo
09-06-2010, 07:05 PM
Hello,

I'm trying to parse my data from an xml file now and print it out on the page based on date from my existing code. I have that working, with each item formatted the same way on the page What I'd like to do now is alter it a bit to make the most recent (the item listed on the top of the page) formatted differently and the rest of them as it is now. Something like - (if 1st <li> then build html like this else build html like that) I hope this makes sense.


<?xml version="1.0" encoding="utf-8" ?>
<books>
<book title="CSS Mastery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/css.jpg">
<description>
08/01/2010 - Content
</description>
</book>

<book title="Professional ASP.NET" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/asp.jpg">
<description>
08/02/2010 - Content
</description>
</book>

<book title="Learning jQuery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/lj.jpg">
<description>
08/03/2010 - Content
</description>
</book>

<book title="Learning jQuery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/lj.jpg">
<description>
08/04/2010 - Content
</description>
</book>

<book title="Learning jQuery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/lj.jpg">
<description>
08/05/2010 - Content
</description>
</book>

</books>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Load XML With jQuery</title>
<script src="jquery-1.2.6.js" type="text/javascript"></script>
<link href="StyleSheet.css" rel="stylesheet" type="text/css" />

<script type="text/javascript">

$(document).ready(function()
{

/*Gets current date*/
var m_names = new Array("January", "February", "March",
"April", "May", "June", "July", "August", "September",
"October", "November", "December");

var date = new Date();
/*var curr_date = d.getDate();*/
var curr_date = 3;
var curr_month = date.getMonth();
var curr_year = date.getFullYear();


$.get('myData.xml', function(d){
/* $('body').append('<h1> Title</h1>');*/
$('#col-a').append('<ul id="tips"/>');

$(d).find('book').each(function(){

var $book = $(this);
var title = $book.attr("title");
var description = $book.find('description').text();
var imageurl = $book.attr('imageurl');

var html = '<li class="tipItem" style="list-style:none;display: none; li">';
html += '<img class="bookImage" alt="" src="' + imageurl + '" /> ';
html += '<p class="title">' + title + '</p>';
html += '<p> ' + description + '</p>' ;
html += '</li>';

$('ul').append($(html));

});

var tips = $('#tips .tipItem');

tips.each(function(i) {
if (curr_month == 8 && curr_date <= i){
$(this).hide();
} else {
$(this).show();
}
});

tips = $.makeArray(tips);
tips.reverse();
$(tips).appendTo(document.getElementById('tips')
);


});
});




</script>

</head>
<body>
<div id="col-a"></div>
</body>
</html>

jscheuer1
09-07-2010, 01:41 AM
Replace:


$(tips).appendTo(document.getElementById('tips')
);

with:


$(tips).appendTo(document.getElementById('tips')).each(function(){
if(this.style.display !== 'none'){
$(this).addClass('theFirst');
return false;
}
});

Now the first displayed tip li will have a class name of 'theFirst'. So, for example, you can add this rule to (preferably the end of) your stylesheet:


.theFirst .title {
color: red;
}

Full code of my working local mock up:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Load XML With jQuery</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<link href="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/StyleSheet.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.theFirst .title {
color: red;
}
</style>
<script type="text/javascript">

$(document).ready(function()
{

/*Gets current date*/
var m_names = new Array("January", "February", "March",
"April", "May", "June", "July", "August", "September",
"October", "November", "December");

var date = new Date();
/*var curr_date = d.getDate();*/
var curr_date = 3;
var curr_month = date.getMonth();
var curr_year = date.getFullYear();


$.get('myData.xml', function(d){
/* $('body').append('<h1> Title</h1>');*/
$('#col-a').append('<ul id="tips"/>');

$(d).find('book').each(function(){

var $book = $(this);
var title = $book.attr("title");
var description = $book.find('description').text();
var imageurl = $book.attr('imageurl');

var html = '<li class="tipItem" style="list-style:none;display: none; li">';
html += '<img class="bookImage" alt="" src="' + imageurl + '" /> ';
html += '<p class="title">' + title + '</p>';
html += '<p> ' + description + '</p>' ;
html += '</li>';

$('ul').append($(html));

});

var tips = $('#tips .tipItem');

tips.each(function(i) {
if (curr_month == 8 && curr_date <= i){
$(this).hide();
} else {
$(this).show();
}
});

tips = $.makeArray(tips);
tips.reverse();
$(tips).appendTo(document.getElementById('tips')).each(function(){
if(this.style.display !== 'none'){
$(this).addClass('theFirst');
return false;
}
});
});
});




</script>

</head>
<body>
<div id="col-a"></div>
</body>
</html>

Note: I'm using the latest 1.4x version of jQuery. But this also works with the 1.2.6 version you appear to be using. 1.4x is much more efficient though. there are some minor differences, none that affect this code.

bigalo
09-07-2010, 01:19 PM
Thanks John,
This is close, I actually wanted to rebuild the html in a different format as well. So essentially, I would have something like:

If(whatever = the first li) {
var html = '<li class="tipItem" style="list-style:none;display: none; li">';
html += '<p class="title">' + title + '</p> ';
html += '<img class="bookImage" alt="" src="' + imageurl + '" />';
html += '<p> ' + description + '</p>' ;
html += '<p> ' + description + '</p>' ;
html += '</li>';

} else {
var html = '<li class="tipItem" style="list-style:none;display: none; li">';
html += '<img class="bookImage" alt="" src="' + imageurl + '" /> ';
html += '<p class="title">' + title + '</p>';
html += '<p> ' + description + '</p>' ;
html += '</li>';

}

Also, What is needed for this to work in IE?

jscheuer1
09-07-2010, 02:23 PM
It's funny that you should use the word 'rebuild', as that would probably be easier given the current flow of your code. What your snippet shows however is building it differently to begin with. The easiest way to rebuild would be to maintain a reference to the data:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Load XML With jQuery</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<link href="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/StyleSheet.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.theFirst .title {
color: red;
}
</style>
<script type="text/javascript">

$(document).ready(function()
{

/*Gets current date*/
var m_names = new Array("January", "February", "March",
"April", "May", "June", "July", "August", "September",
"October", "November", "December");
var bookdata;
var date = new Date();
/*var curr_date = d.getDate();*/
var curr_date = 3;
var curr_month = date.getMonth();
var curr_year = date.getFullYear();


$.get('myData.xml', function(d){
/* $('body').append('<h1> Title</h1>');*/
$('#col-a').append('<ul id="tips"/>');
bookdata = $(d).find('book');
bookdata.each(function(i){

var $book = bookdata.eq(i);
var title = $book.attr("title");
var description = $book.find('description').text();
var imageurl = $book.attr('imageurl');

var html = '<li class="tipItem" style="list-style:none;display: none;">';
html += '<img class="bookImage" alt="" src="' + imageurl + '" /> ';
html += '<p class="title">' + title + '</p>';
html += '<p> ' + description + '</p>' ;
html += '</li>';

$('ul').append($(html).data('data_book', i));

});

var tips = $('#tips .tipItem');

tips.each(function(i) {
if (curr_month == 8 && curr_date <= i){
$(this).hide();
} else {
$(this).show();
}
});

tips = $.makeArray(tips);
tips.reverse();
$(tips).appendTo(document.getElementById('tips')).each(function(){
if(this.style.display !== 'none'){
var theFirst = $(this);
var idx = theFirst.data('data_book');
var $book = bookdata.eq(idx);
var title = $book.attr("title");
var description = $book.find('description').text();
var imageurl = $book.attr('imageurl');

var html = '<li class="tipItem" style="list-style:none;">';
html += '<p class="title">' + title + '</p> ';
html += '<img class="bookImage" alt="" src="' + imageurl + '" />';
html += '<p> ' + description + '</p>' ;
html += '<p> ' + description + '</p>' ;
html += '</li>';
theFirst.remove();

$('ul').prepend($(html).data('data_book', idx).addClass('theFirst'));
return false;
}
});
});
});




</script>

</head>
<body>
<div id="col-a"></div>
</body>
</html>

About IE - Works fine live. Locally it's a blank page.

Note1: Depending upon how an AJAX routine is written (if it lacks an IE 7+ fall back to Active X for local implementations, which is sort of dishonest anyway), IE 7 and up will block it locally for security reasons. Chrome can too, though not all the time. For these and other reasons I test all my AJAX stuff on my local host sandbox (I use WAMP). It's also good for some frame and iframe, and communication between windows things, as these are all cross domain sensitive. In some browsers when run locally if all pages and resources aren't in the same folder they may be seen as on different domains.

Same thing (folders seen as domains) for Chrome and AJAX I think. Firefox can do this with frames/iframes. For IE and AJAX it's a slightly different mechanism, but amounts to the same thing.

Note2: Since an image(s) is/are involved, there might be problems in IE if the image hasn't fully loaded yet before the li is removed. If so, a workaround can be devised.

bigalo
09-07-2010, 02:41 PM
This Perfect!!!! Thanks so much John! This is exactly what I was looking for. Also, thanks for the tip on the localhost, I never thought about that factor.

jscheuer1
09-08-2010, 01:35 AM
I'm not sure about perfect. Nobody/nothing is. Anyways, here's how I would write it:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Load XML With jQuery</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<link href="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/StyleSheet.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.theFirst .title {
color: red;
}
</style>
<script type="text/javascript">

jQuery(function($){

/* Set Variables */
var m_names = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
bookdata, bookHTML = [], date = new Date(), /* curr_date = d.getDate(), */curr_date = 3, curr_month = date.getMonth(),
curr_year = date.getFullYear(), $book, title, description, imageurl, idx, firstCompleted = false;


$.get('myData.xml', function(d){
/* $('body').append('<h1> Title</h1>'); */
$('#col-a').append('<ul id="tips"/>');
bookdata = $.map($(d).find('book'), function(n){return $(n);}).reverse();
$.each(bookdata, function(i){
if(curr_month === 8 && i + 1 >= curr_date){
$book = bookdata[i];
title = $book.attr("title");
description = $book.find('description').text();
imageurl = $book.attr('imageurl');

if(firstCompleted){
bookHTML.push(['<li class="tipItem" style="list-style:none;">',
'<img class="bookImage" alt="" src="' + imageurl + '" /> ',
'<p class="title">' + title + '</p>',
'<p> ' + description + '</p>',
'</li>'].join(''));
} else {
bookHTML[0] = ['<li class="tipItem theFirst" style="list-style:none;">',
'<p class="title">' + title + '</p> ',
'<img class="bookImage" alt="" src="' + imageurl + '" />',
'<p> ' + description + '</p>',
'<p> ' + description + '</p>',
'</li>'].join('');
firstCompleted = true;
}
}
});

$('ul').append(bookHTML.join(''));
});
});
</script>

</head>
<body>
<div id="col-a"></div>
</body>
</html>

Notes: This also gets rid of any possibility that IE will have to deal with loading images being removed (something it often doesn't react well to).

There's one thing about this that disturbs me, the curr_date and how that and the curr_month relate to the selecting of what content to show. In your example you chose an arbitrary number that suited the xml file's contents for the date and hard coded the expected month # into the if statement. I've followed suit above.

It remains to be seen if, when actually using the live date, this will be workable. I'm imaging though that the value in each xml book element that is currently in the description tags, ex:


<book title="CSS Mastery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/css.jpg">
<description>
08/01/2010 - Content
</description>
</book>

could be parsed (would require at least some additional code*) in order to get things to work out in a real example of this. Doing so probably will also require tweaking of the if:


if(curr_month === 8 && i + 1 >= curr_date)

I've tried to preserve variables that are not in use but could be, as well as the commented out sections of the code from your initial example that could still be used for something. The date part for sure. I'm not certain what exactly you were going for with the <h1> Title</h1> thing. But I can imagine a few scenarios. You might want to prepend, rather than append it to the body.



*I have what appears to be a solid idea for parsing the date for the description and using it to determine which 'books' get shown.

bigalo
09-08-2010, 02:01 PM
Thanks so much John,

One other question. I'll probably need to use CDATA in my xml file. I tried to parse it out and it's not working correctly. Is there something in the code that I need to adjust to use CDATA?


<tiplink><![CDATA[<a name="" href="#">test link</a>]]></tiplink>

I think I read somewhere that you would have to use a code snippet like similar to this to parse it out:


$(function(){

var xmlDoc;

$.ajax({
type: "GET",
url: "product-info.xml",
dataType: ($.browser.msie) ? "text" : "xml",
global: true,
cache: false,
success: setUpXml
});

function setUpXml(data){

if ( $.browser.msie ) {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(data);
}else{
xmlDoc = data;
}

xmlDoc = $(xmlDoc);
yourfunction();
}

Is that the case, if so, how would I do that with my existing code?

jscheuer1
09-08-2010, 03:36 PM
I see the problem. Where are you getting your information from as to the workaround?

bigalo
09-08-2010, 03:39 PM
That ideas was just an idea. I'll be fine with what I currently have. Thanks anyway.

jscheuer1
09-08-2010, 04:11 PM
Wait a minute, I don't see the problem. IE was caching the xml file for some reason. You can just use a regular link tag and get the href off of it.

jscheuer1
09-08-2010, 04:41 PM
Here's a new demo with some other improvements:


<?xml version="1.0" encoding="utf-8" ?>
<books>
<book title="CSS Mastery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/css.jpg">
<description>
08/01/2010 - Content
</description>
<a href="http://www.google.com/">Google</a>
</book>

<book title="Professional ASP.NET" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/asp.jpg">
<description>
08/02/2010 - Content
</description>
<a href="http://www.google.com/">Google</a>
</book>

<book title="Learning jQuery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/lj.jpg">
<description>
08/03/2010 - Content
</description>
<a href="http://www.dynamicdrive.com/">Dynamic Drive</a>
</book>

<book title="Learning jQuery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/lj.jpg">
<description>
08/04/2010 - Content
</description>
<a href="http://www.google.com/">Google</a>
</book>

<book title="Learning jQuery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/lj.jpg">
<description>
08/05/2010 - Content
</description>
<a href="http://www.google.com/">Google</a>
</book>

</books>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Load XML With jQuery</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<link href="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/StyleSheet.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.theFirst .title {
color: red;
}
</style>
<script type="text/javascript">
/* <![CDATA[ */
jQuery(function($){

/* Set Variables */
var m_names = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
bookdata, bookHTML = [], date = new Date('08/03/2010'), curr_date = date.getDate(), curr_month = date.getMonth(), link, linktext,
curr_year = date.getFullYear(), bookstamp, bookmonth, bookdate, $book, title, description, imageurl, idx, firstCompleted = false;


$.ajax({url: 'myData.xml', cache: false, success: function(d){

$('body').prepend('<h1>Books for - '+ m_names[curr_month] + ' ' + curr_date + ', ' + curr_year + ':</h1>');
$('#col-a').append('<ul id="tips"/>');
bookdata = $.map($(d).find('book'), function(n){return $(n);}).reverse();
$.each(bookdata, function(i){
$book = bookdata[i];
description = $.trim($book.find('description').text());
bookstamp = new Date(description.substring(0, 10));
bookmonth = bookstamp.getMonth();
bookdate = bookstamp.getDate();
if(curr_month === bookmonth && bookdate <= curr_date){
title = $book.attr("title");
imageurl = $book.attr('imageurl');
link = $book.find('a').attr('href');
linktext = $book.find('a').text();

if(firstCompleted){
bookHTML.push(['<li class="tipItem" style="list-style:none;">',
'<img class="bookImage" alt="" src="' + imageurl + '" /> ',
'<p class="title">' + title + '</p>',
'<p>' + description + '</p>',
'<p><a href="' + link + '">' + linktext + '</a></p>',
'</li>'].join('\n'));
} else {
bookHTML[0] = ['<li class="tipItem theFirst" style="list-style:none;">',
'<p class="title">' + title + '</p> ',
'<img class="bookImage" alt="" src="' + imageurl + '" />',
'<p>' + description + '</p>',
'<p>' + description + '</p>',
'<p><a href="' + link + '">' + linktext + '</a></p>',
'</li>'].join('\n');
firstCompleted = true;
}
}
});

$('ul').append(bookHTML.join('\n\n'));
}});
});
/* ]]> */
</script>

</head>
<body>
<div id="col-a"></div>
</body>
</html>

One important thing to note. See the highlighted date. Remove that for a live installation. It is required only so as to work with the static xml file above. I'm assuming in 'real life' this xml file is generated by the server, right?

The above code parses the a tag just fine in IE and others without the need fo CDATA delimiters, which as far as I know are only required for things like scripts and stylesheets, which shouldn't really be in an xml file of this type anyway.

I've also added/changed code to ensure IE doesn't cache the xml file.

bigalo
09-09-2010, 12:41 AM
I've decided to just build out the hrefs in the code instead. and parse the link url from the xml file.


Thanks!

jscheuer1
09-09-2010, 01:05 AM
OK, well though - I'm still not sure what you were getting at. It now seems to me that you wanted to be able to import the a tag wholesale - not parse it, just use it 'as is'. That might be possible using CDATA delimiters in the xml file. It definately is possible if you import the file as text (instead of as currently as an xml document object). You could perhaps even do both, take the xml info from the xml import, and the HTML info from the text import.

Added Later:

I had a closer look at the code you posted in post #7 in this thread. That may or may not have been required in earlier versions of jQuery. But the version (1.4x) I've been using in all of my examples does that for you such that the resulting data (d) in our function is an xml document object in all modern browsers including IE (6 and up, no jQuery works in earlier IE versions) with no need to resort to all that added code or branching. So, if you want to use CDATA in your xml document, it should work the same way in IE as it does in others.

Still Later:
I tried this out, and I can:

xml node:


<book title="Learning jQuery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/lj.jpg">
<description>
08/03/2010 - Content
</description>
<link><![CDATA[<a href="http://www.dynamicdrive.com/">Dynamic Drive</a>]]></link>
</book>

Once I get a reference to that book node (this in the below), I can:


$('body').append(this.find('link').text());

and it puts the complete a tag right there, in this case at the end of the body.

This works with IE as well as (I'm assuming) all other modern browsers, tested in IE 6, 8, Firefox.

bigalo
09-09-2010, 06:52 PM
YES! this is what I was trying to figure out. I'll give it a try! Thanks again.

jscheuer1
09-09-2010, 08:32 PM
To that end, this is my latest revision:

xml:


<?xml version="1.0" encoding="utf-8" ?>
<books>
<book title="CSS Mastery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/css.jpg">
<description>
08/01/2010 - Content
</description>
<link><![CDATA[<a href="http://www.google.com/">Google</a>]]></link>
</book>

<book title="Professional ASP.NET" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/asp.jpg">
<description>
08/02/2010 - Content
</description>
<link><![CDATA[<a href="http://www.google.com/">Google</a>]]></link>
</book>

<book title="Learning jQuery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/lj.jpg">
<description>
08/03/2010 - Content
</description>
<link><![CDATA[<a href="http://www.dynamicdrive.com/">Dynamic Drive</a>]]></link>
</book>

<book title="Learning jQuery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/lj.jpg">
<description>
08/04/2010 - Content
</description>
<link><![CDATA[<a href="http://www.google.com/">Google</a>]]></link>
</book>

<book title="Learning jQuery" imageurl="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/images/lj.jpg">
<description>
08/05/2010 - Content
</description>
<link><![CDATA[<a href="http://www.google.com/">Google</a>]]></link>
</book>

</books>

HTML:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Load XML With jQuery</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<link href="http://cdn.net.tutsplus.com/045_LoadXMLWithJquery/StyleSheet.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.tipItem {
list-style: none;
}
.theFirst .title {
color: red;
font-size: 160%;
}
</style>
<script type="text/javascript">
/* <![CDATA[ */
jQuery(function($){

/* Declare Variables */
var m_names = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
nth_names = ['st', 'nd', 'rd', 'rth'], th1, th2, date = new Date('08/03/2010'), curr_date = date.getDate(), curr_month = date.getMonth(),
curr_year = date.getFullYear(), curr_time = date.getTime(), bookHTML = [], bookstamp, title, description, imageurl, link, firstCompleted;

function nth(n){
n = n.toString(10); th1 = n.substr(-1); th2 = n.substr(-2);
return n + (th2 > 10 && th2 < 15? 'th' : nth_names[--th1]? nth_names[th1] : 'th');
}

$('body').prepend('\n<h1>Books for - '+ m_names[curr_month] + ' ' + nth(curr_date) + ' ' + curr_year + ':</h1>\n');

$.ajax({url: 'myData.xml', cache: false, success: function(d){
$('#col-a').append('\n<ul id="tips"/>\n');
$.each($.map($(d).find('book'), function(n){return $(n);}).reverse(), function(){
description = $.trim(this.find('description').text());
bookstamp = new Date(description.substring(0, 10)).getTime();
if(bookstamp <= curr_time){
title = this.attr("title");
imageurl = this.attr('imageurl');
link = this.find('link').text();
if(firstCompleted){
bookHTML.push(['\t<li class="tipItem">',
'\t<img class="bookImage" alt="" src="' + imageurl + '" /> ',
'\t<p class="title">' + title + '</p>',
'\t<p>' + description + '</p>',
'\t<p>\t' + link + '\t</p>',
'</li>'].join('\n\t'));
} else {
bookHTML[0] = ['\n\t<li class="tipItem theFirst">',
'\t<p class="title">' + title + '</p> ',
'\t<img class="bookImage" alt="" src="' + imageurl + '" />',
'\t<p>' + description + '</p>',
'\t<p>' + description + '</p>',
'\t<p>\t' + link + '\t</p>',
'</li>'].join('\n\t');
firstCompleted = true;
}
}
});
$('ul').append(bookHTML.join('\n\n') + '\n');
}});
});
/* ]]> */
</script>

</head>
<body>
<div id="col-a"></div>
</body>
</html>

Notes: Once again the highlighted date in the HTML file should be removed for a live installation assuming that the xml file will be generated in real time by the server.

I've been thinking that, depending upon when you want the content presented to whom, that the current date (date = new Date()) info should perhaps come from the server via PHP's date function.

Also added in this version:

A function to give the current date a suffix like 'nd' or 'rd' or 'th' depending upon what number it is. This, if we pull the current date from the server via PHP or even if we don't, can optionally be done on the server side in PHP where there already is an established routine for it.

And a more accurate way of determining if any given content is timely.