RSS and AJAX: A Simple News Reader
by Paul Sobocinski
|
Pages: 1, 2, 3, 4, 5
Use of the eval() Function
Before I continue, I wanted to briefly explain the eval() function, in case you're unfamiliar with it. This function takes a single argument, which is a string containing the JavaScript code that you want your program to run. For example, eval('return true') is identical to return true. As you will see, this function is useful when dealing with objects that have a large number of properties.
D: We will now set all of the object properties that take simple strings as their values. As all of these properties are grabbed from the chanElement object in the same way, we define an array containing the names of all the properties we want to set, and traverse the array using a for loop. To get the actual string value of the XML tag we are examining, we access two properties: childNodes and nodeValue. The first property exposes all of the child XML elements in the form of an array of objects, while the second property gets the actual string value of the XML element. In the case of the properties being retrieved here, they do not contain any child XML tags, so only one element is returned by childNodes. Then, nodeValue gets the string value of the element in childNodes[0].
E: Finally, we set the this.category and this.image properties. Unlike the properties discussed in D, these do have child tags, so we have to construct custom objects for these XML elements (RSS2Category and RSS2Image, respectively). Let's have a look at the RSS2Category function to start:
function RSS2Category(catElement)
{
if (catElement == null) {
this.domain = null;
this.value = null;
} else {
this.domain = catElement.getAttribute("domain");
this.value = catElement.childNodes[0].nodeValue;
}
}
This is a simple object with two properties: domain and value. The value property contains the actual contents of the XML tag, while the domain property is set to the contents of the XML domain tag attribute. For example, a typical category XML element looks like this: <category domain="Syndic8">1765</category>. In this case, this.domain is set to Syndic8 and this.value is set to 1765. In order to get the domain attribute from the XML tag, we use the function getAttribute() and pass the tag attribute we want to fetch as a parameter (in this case, domain).
As the image tag in an RSS XML file has only attributes, the RSS2Image constructor makes use of the getAttribute() function extensively.
function RSS2Image(imgElement)
{
if (imgElement == null) {
this.url = null;
this.link = null;
this.width = null;
this.height = null;
this.description = null;
} else {
imgAttribs = new Array("url","title","link","width","height","description");
for (var i=0; i<imgAttribs.length; i++)
if (imgElement.getAttribute(imgAttribs[i]) != null)
eval("this."+imgAttribs[i]+"=imgElement.getAttribute("+imgAttribs[i]+")");
}
}
Now we'll go onto the last remaining property in the RSS2Channel object: items, which contains an array of RSS2Item objects. The code for this object is shown below:
function RSS2Item(itemxml)
{
/*A*/
/*required properties (strings)*/
this.title;
this.link;
this.description;
/*optional properties (strings)*/
this.author;
this.comments;
this.pubDate;
/*optional properties (objects)*/
this.category;
this.enclosure;
this.guid;
this.source;
/*B*/
var properties = new Array("title", "link", "description", "author", "comments", "pubDate");
var tmpElement = null;
for (var i=0; i<properties.length; i++)
{
tmpElement = itemxml.getElementsByTagName(properties[i])[0];
if (tmpElement != null)
eval("this."+properties[i]+"=tmpElement.childNodes[0].nodeValue");
}
/*C*/
this.category = new RSS2Category(itemxml.getElementsByTagName("category")[0]);
this.enclosure = new RSS2Enclosure(itemxml.getElementsByTagName("enclosure")[0]);
this.guid = new RSS2Guid(itemxml.getElementsByTagName("guid")[0]);
this.source = new RSS2Source(itemxml.getElementsByTagName("source")[0]);
}
The RSS2Item object is similar to RSS2Channel in many ways. We start by listing out the properties that we will be retrieving (A). We then loop through the string properties, and assign each to the contents of its associated XML tag (B). Lastly, we set object properties by calling the appropriate custom object constructor--in each case, passing the XML element that contains the relevant data (C).
The custom objects that are found in the RSS2Item object are listed below. They are similar to the RSS2Category and RSS2Image objects, and they don't use any functions or properties that haven't been discussed earlier.
function RSS2Enclosure(encElement)
{
if (encElement == null) {
this.url = null;
this.length = null;
this.type = null;
} else {
this.url = encElement.getAttribute("url");
this.length = encElement.getAttribute("length");
this.type = encElement.getAttribute("type");
}
}
function RSS2Guid(guidElement)
{
if (guidElement == null) {
this.isPermaLink = null;
this.value = null;
} else {
this.isPermaLink = guidElement.getAttribute("isPermaLink");
this.value = guidElement.childNodes[0].nodeValue;
}
}
function RSS2Source(souElement)
{
if (souElement == null) {
this.url = null;
this.value = null;
} else {
this.url = souElement.getAttribute("url");
this.value = souElement.childNodes[0].nodeValue;
}
}
Now that we've fully defined our RSS object, we can move on to the last step: displaying its actual content.