Latest News Version 2
   
 

Resources: Flash .fla file (Flash MX, zipped), Flash .swf file (Flash Player 6), XML file.

This is an update to the original latest news tutorial. The original tutorial still provides a good introduction to flash and XML. However there where a few things that are pretty lacking with the original version:

When building a site and deciding to go to the effort of using XML there is no point in creating your own standards for your XML documents when defined standards exist. The XML used for the original latest news tutorial is a classic example of creating your own standards. If I wanted to expand the use of the flash program or use the XML in other programs I would have to write all the code. However thousands of other people are already sharing headlines and titles of news and blog articles. If you use a XML standard then it is a simple matter of dropping in other peoples code to manipulate your XML feed. In the case of XML news feeds there is a definite standard, RSS. I won't go into the whys and hows of RSS, however there is an excellent article providing and introduction at xml.com

These days RSS feeds are everywhere with most news sites providing an RSS feed and other sites aggregating the feeds. Where and how you get your RSS feed is up to you, however it does have to be accessible from your website. Flash security will not allow you to go out onto the internet and get someone elses feed, if you want to grab someone elses feed check out the Flash-XML FAQ section on security. For the purposes of this tutorial I am going to use a static XML file.

Here is what a basic rss XML file looks like:

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Flash @ Tupps</title>
<link>http://www.tupps.com/flash</link>
<description>Flash @ Tupps is a unique source of original information about using XML in Macromedia Flash 5, MX and MX 2004</description>
<language>en-us</language>
<item>
<title>Scrolling Text Box</title>
<link>http://www.tupps.com/flash/examples/scrolling_text/demoText.html</link>
<description>This is an example text box that slowly scrolls the content received from an XML file. The user can access the scroll box at any time and move it up and down. </description>
<dc:creator>Luke Tupper</dc:creator>
<dc:date>2003-05-23</dc:date>
</item>
<item>
<title>Displaying a plain text break from a xml file.</title>
<link>http://www.tupps.com/flash/examples/plain_break/demoText.html</link>
<description>This example allows the user to use a plain text breaks in the xml file and display the text correctly in a flash text box. </description>
<dc:creator>Luke Tupper</dc:creator>
<dc:date>2003-04-11</dc:date>
</item>
<item>
<title>Displaying html breaks from a xml file.</title>
<link>http://www.tupps.com/flash/examples/html_break/demoText.html</link>
<description>This example allows the user to use a html text in the xml file and display the text correctly in a flash text box.</description>
<dc:creator>Luke Tupper</dc:creator>
<dc:date>2002-04-09</dc:date>
</item>
</channel>
</rss>

For the latestnews the only items we are interested in are the individual items, and for each item the title and the link.

Another advantage of this latest news display is that it is not difficult to modify it to be a full blown rss news reader. It has been designed so that nearly all of the code written can be reused in another player (feel free to take the code).

This version of the latest news has reduced the number of places that code exists. All of the XML handling code and the code to fade in and out the title is on frame 1 of the layer named 'actions'. The only other code in the flash movie is a clip event on the movie containing the text node that causes the link to fired off when a user clicks on the title.

The first time we parse the xml file we want to find all the item nodes and for each one a title and a link. In the original latest news tutorial I created two arrays to store this information. A better way to do this is to store an array of objects with each object referencing the original node in XML data. This will allow any expansion of our code to handled easily because you will be able to get to the original XML data without having to create another array of data. The other advantage is that we can add methods to the objects to extract the information that we require. Before we jump to parsing the data there are a couple of things we have to be aware of. The most important is that there might be multiple channel tags in the RSS feed. To deal with this we will search the entire XML tree for 'item' nodes, therefore making sure we don't miss anything if the document is rearranged. This will also make our application more robust if the XML changes, and more likely to be backward compatible with older formats of RSS.

First we need to load the XML. The first step is to create the XML object (line 8) When the XML is loaded and parsed we want flash to call the extractData function, this is assigned on line 9. Flash implements this as a call back, so if you are tracing through this code you will find that extractData is called after the rest of the code on frame 1 has been run. Finally we tell the xml object to load ourXML file (line 10). If the XML file is in a different directory you will have to specify an exact path (eg. /newsfeed/rss.xml) or as a relative path (eg. ../../rss.xml).

//Load the XML 
rssXML = new XML();
rssXML.onLoad = extractData;
rssXML.load("rss20.xml"); //Link to the rss20.xml file in the same directory as the flash file.

(lines 7-10)

The extractData function is responsible for making sure that the XML has been loaded correctly (line 17). If everything is loaded and parsed correctly by the flash player then we call the parseTree function (line 22). The parseTree function will 'walk' through all of the nodes in the XML looking for item nodes.

When parseTree has finished the itemsArray should be populated with an array of items from the XML file. I have left a trace statement here that I used in my original testing to make sure everything was working correctly. I always use the philosphy if you have put in trace statement to get some critical information for debugging then you might as well leave it in so that the next time you want that information it will be there ready for you. Plus having tonnes of scrolling text on your screen always makes it seem as though you know what you are doing ;-)

The final call is to the showText routine. This routine (which I don't outline in this tutorial) is responsible for making the text display and disappear at various points. Also the first time the routine is run and every time the text fades out it will choose a new random text string to display (see getNewText function line 113).

If the extractData function cannot load or process the XML file it should have a better warning than simply outputting a trace statement. I will leave that up to you to do.

//This function gets called when the XML has fully loaded
function extractData(success)
{
//Success will be true if flash could open and parse all the XML content.
if (success) //Line 17
{
//Within the function in the callback from the XML onLoad statement
//the variable 'this' refers to the XML document that has been
//successfully loaded by XML function.
parseTree(this);//Line 22

trace("Array Length: " + itemsArray.length); //How many records did we find?

//Now start the latest news rolling:
showText();
}
else
{
//Should have a failure handler here!
trace("XML Load Failed");
}
trace("Finised Extracting");
}

(Lines 13-38)

The parseTree function is a recursive function call, a node is passed to the parseTree function, if that node contains other nodes then each of those childNodes are checked by a new instance of the parsTree function to see if they are an item node. The for loop is used to go through each child node one at a time. I have left the trace statement in so it is easy to check that the system is parsing the entire XML file. If we encounter an item node we will call the extractItem function. If we encounter anything else we will call the parseTree function again.

If you haven't programmed with recursive functions call this can be a bit of mind bender and can be tricky to debug. However this method of parsing XML files is great if you are not in control of the format of the XML file. Flash can make up to 256 recursive calls before its call stack (the thing to keep track of which functions have called other functions) is full. In a practical sense this means that we can parse a XML file that is up to 250 or so nodes deep (eg firstNode.firstNode.firstNode would be 3 nodes deep), I doubt there are many XML files out there that have a node heirachy greater than 250 nodes deep. Note: this is not how many nodes and XML file has but how many parents a node has. Most XML files are 2-6 nodes deep and complicated XML files might have a hierachy with more than 10 nodes. 250 nodes seems would be an extremely complicated XML file.

function parseTree(xmlNode) 
{
//Go through each node, if it is an item node then add items to the itemsArray
//Else go through each of the child nodes and recursively call this function
//foreach child node. Note item nodes inside other item nodes will not be found.

trace("Parsing this: " + xmlNode.toString()); //Used for initial debugging to make sure xml parsing is working.

if (xmlNode.hasChildNodes())
{
//Something funny in the parsing here.
for (var i = 0; i < xmlNode.childNodes.length; i++)
{
trace("xmlNode.childNodes[" + i + "].nodeName: " + xmlNode.childNodes[i].nodeName);
if (xmlNode.childNodes[i].nodeName == "item")
{
//Extract the RSS item
extractItem(xmlNode.childNodes[i]);
} else
{
//Call parseTree to scavenge through this nodes childNodes
parseTree(xmlNode.childNodes[i]);
}

}
}
}

(lines 37-63)

The final part of our program for dealing with the XML file is the extractItem function. This routine is fairly simple because most of the actually data handling is done in our newsItem object (lines 173-200). The object is initialised with the XML node (line 77). If the user requests a title or the link function this will call a routine that searches and extracts the relevant details. If both of the title and link exist (if they don't our program would not display any information, or you couldn't go to the article) we will add the new object to our array of news items.


function extractItem(xmlNode)
{
//This function adds an item to the array of items that will be used for
//latest news.
//We need to find two items, the title, and the link url. If either of them
//are not found then we needn't bother adding this item to the array.

var title = null;
var link = null;
if (xmlNode.hasChildNodes())
{
var newsItem = new newsItem(xmlNode);

trace("Title: " + newsItem.title() + " Link: " + newsItem.link());
if (newsItem.title() != null && newsItem.link() != null) //check to make sure the title and link have been set.
{
//Assign it into the array.
itemsArray.push(newsItem);
}
}
}

(lines 65-86)

The newsItem object is the one that is responsible for doing the last steps in the XML extraction. In our case the object has 1 property and 2 functions. The property is the xmlNode. This contains the item xml data. The two functions get the title and the link for us. The function calls getTitle and getLink are called and they in tern call the findNode function, passing the appriorate name to be retreived. If you wanted to expand this application to receive other information (descriptions, author name, etc) then you would start by adding additional functions similar to getTitle and getLink, then add them to the newsItem object.

//Class constructor
function newsItem(xmlNode)
{
this.xmlNode = xmlNode;
this.title = getTitle;
this.link = getLink;
}
function getTitle()
{
return findNode(this.xmlNode, "title");
}
function getLink()
{
return findNode(this.xmlNode, "link");
}
function findNode(xmlNode, nodeName)
{
for (var i = 0 ; i < xmlNode.childNodes.length; i++)
{
if (xmlNode.childNodes[i].nodeName == nodeName)
{
return xmlNode.childNodes[i].firstChild.nodeValue;
}
}
}

(Lines 173-200)

In aproximately 100 lines of code including comments and whitespace we have extracted our XML files and are ready to display them. Three additional routines showText, hideText and getNewText exist to handle the fading in and out of the text. This is done using a timer that is continously set by these routines to call themselves in a short period of time. Be aware that if you use these routine and are trying to fade text in and out that you must embed the outlines of the text, otherwise the text won't allow color transformation effects to be applied (I can tell you that was a fun thing to nut out!).