logo for mobile version

Reading news feeds with XMLSA

Reading news feeds with XMLSA

I used to hate XML and all the looping across nodes to get data. Then I found a class called XMLSA, created by Max Ziebell. Using XMLSA, making a RSS news ticker/reader is easy.

This tutorial requires intermediate programming experience with knowledge about Arrays and XML. If you don't know what Arrays are, learn it here 1, 2, 3)

In this tutorial, you'll learn how to build your own little RSS newsreader like this.

If you've surfed around blogs, you've probably seen small buttons saying "RSS". Clicking the button will prompt a download, so RSS is not something your average browser knows how to handle.

RSS is a format for syndicating news and the content of news-like sites. RSS is not difficult. It's just XML that is structured in a special way, so that others can make use of it. Macromedia is using RSS files for aggregating news feeds related to Flash and other products at markme.com.

The headlines of Flashmagazine are also available as a RSS file. Download the file, open it an your favorite text editor and take a look at how the XML is structured. We have a root node called rss. Next, we have a channel node and beneath that there are item nodes for each news story. These are the nodes with the data we need.

Working with XML files using Flash can be tiresome, but thanks to XMLSA, written by Max Ziebell, it's just as easy as reading data from an array. XMLSA works as a layer on top of the built in XML methods of Flash. It's a class that makes reading XML and building XML a breeze. Why should you parse a tree with nodes just to access a data item? Why not access it directly as with arrays? All you have to do to use XMLSA, is to copy it into an .as file and include it in your projects. You can download the latest version of XMLSA from layer51. You will find it in the first scrollable textfield. Copy all the text into a file and name it xmlsa.as.

Setting up the file

Create a new Flash file and save it in the same directory as the xmlsa.as file. In the first frame, open the Actionscript panel and type:

#include "XMLSA.as"


This will load XMLSA and all it's methods. Next, we want to load the RSS file. The methods of XMLSA are just like for the XML object in Flash:

news = new XMLSA();

news.load("http://www.flashmagazine.com/syndicated/flashmag.rss");

news.onLoad = function(success){

if (success) {

trace("success");

} else {

trace("Error loading XML");

}

}


When you have entered the code above, press CTRL+SHIFT+ENTER to test the file with the debugger open. Press play on the debugger to start playing the movie. When the movie starts, XMLSA loads the file and parses it into an array. Under the variables tab, you will find the object news with subnodes for every element in the RSS document.

Flash Debugger window

The XML is now an array that you can access the way you usually access them. The root node of the XML is the same as the news-object we just created.

Accessing the data

To access the attributes of the root XML element (rss), you use the path news.attributes.version. This is the same for any attribute anywhere in the XML document.

Any element in the XML is an array, so to find how many news stories the RSS document contains, simply use news.channel[0].item.length.

To get the text of an element, use the getValue-function on a element: news.channel[0].item[0].title.getValue().

Let's extend the onLoad method to print out these three values.

news.onLoad = function(success){

if (success) {

trace("success");

trace(news.attributes.version);

trace(news.channel[0].item.length);

trace(news.channel[0].item[0].title.getValue());

} else {

trace("Error loading XML");

}

}


As you can see from the output panel, we are tracing out the values from the XML, just as if they were arrays. Now we have what we need to grab the data from the RSS file. Now we need to display them. Make two text fields. Give the first an instance name of head and the second body. (Make sure you do not type this in the variables fields.) Set both fields to multiline, make the document 250 by 250 pixels. Scale the text fields so they are one line high and almost as wide as the movie.

Presenting the data

Klick the first frame again and type in the following function:

// Function for getting next entry

showNext = function(){

// Zero the counter if the last article has been shown

if(rssCounter == rssCount || rssCounter == undefined){ rssCounter = 0; }

// Get values from XMLSA array

head.text = newsNode.item[rssCounter].title.getValue();

body.htmlText = newsNode.item[rssCounter].description.getValue();

rssURL = newsNode.item[rssCounter].link.getValue();

// Increment the counter

rssCounter++;

}


The showNext-function will fill in the text fields with the data from the XML file. Every time the function is called, a counter is incremented so that a new story is picked the next time the function is called. We'll also need a transparent button on top of the stories. The button will open up a new window with the URL we are storing in the variable rssURL. Put the following script on the button.

on(release){

getURL(rssURL,"_blank");

}


By creating an interval in the news.onLoad-function, we'll call this function every time we want the news story to update. We also need to store the number of stories before we need to loop.

news = new XMLSA();

news.load("http://www.flashmagazine.com/syndicated/flashmag.rss");

news.onLoad = function(success){

if (success) {

// Store the number of news items

rssCount = news.channel[0].item.length;

// Call the showNext function every 5 seconds

setInterval(showNext,5000);

} else {

trace("Error loading XML");

}

}


If you test the file now, the XML should fill into the fields, but the text will only display on one line. We need to set the autoSize property for the text fields for this to work correctly. Put these two lines just after the include-statement.

body.autoSize = "right";

head.autoSize = "right";


If the heading should need to be displayed over two lines, it will overlap the body-text. If we fill data in an autosized field, the field will resize instantly. This makes positioning easy. We just fill in the text and we can then use the height of the header textfield to offset the body textfield. We do this by adding the following line to the showNext-function.

body._y = head._y + head._height;


Solving RSS versions

RSS comes in multiple flavors. Flashmagazine is using the old, but valid 0.91 version. Since this was created, versions 1.0 and 2.0 have arrived. Both of these have a slightly different XML structure. To make our script eat any valid RSS file, we'll have to detect what version of RSS is loaded. This is done by checking against the object news.channel[0].item. If this object exists, the RSS is version 0.91. If not, the version number should be RSS1.0 or RSS2.0 and they're both similar in structure.

With this detection included, the final script is like this.

#include "XMLSA.as"

// Setup text fields

body.autoSize = "right";

head.autoSize = "right";

body.text = "Loading news stories";

// URL if the user clicks before data is loaded

rssURL = "http://www.flashmagazine.com";

// Load the XML/RSS

news = new XMLSA();

// Load the RSS file

news.load("http://www.flashmagazine.com/syndicated/flashmag.rss");

news.onLoad = function(success){

if (success) {

// Check RSS version and make shorthand

if(news.channel[0].item){

// Where to find data items for RSS 1.0

newsNode = news.channel[0];

} else {

// Where to find data items for RSS 0.91 and 2.0

newsNode = news;

}

// Store the number of news items

rssCount = newsNode.item.length;

// Call the showNext function every 5 seconds

setInterval(showNext,5000);

} else {

// Show error message

body.text = "Error loading XML";

}

}

// Function for getting next entry

showNext = function(){

// Zero the counter if the last article has been shown

if(rssCounter == rssCount || rssCounter == undefined){ rssCounter = 0; }

// Get values from XMLSA array

head.text = newsNode.item[rssCounter].title.getValue();

body.htmlText = newsNode.item[rssCounter].description.getValue();

rssURL = newsNode.item[rssCounter].link.getValue();

// Position the body text below the heading

body._y = head._y + head._height;

// Increment the counter

rssCounter++;

}


To keep users informed, we're setting the body.text field both before loading and if loading the XML should fail. XMLSA takes the pain out of working with XML. Working with arrays is just so much easier. XMLSA also has a small debug section that will let you display the XML produced and a couple other nifty features.

Crossing domains

From version 7, the Flash Player has a restriction that prevents data to be loaded from other domains than the originating one. The loading of data isn't prevented alltogether, but a dialogue will display, alerting the user that data is loaded from a different domain than the SWF file is on.

To prevent this dialogue popping up, you'll need a crossdomain.xml file. This file must be placed at the root of the server where the data is loaded from. Here is a link to the one that is currently in use at Flashmagazine.com. You can read a good explanation of this problem here. If you do not own the domain where the RSS resides, you'll get problems uploading the crossdomain.xml file. There are several ways to get around this if you know just a little bit of serverside scripting and have your own server.

Taking it further

Now we have a file that can look up a RSS file and display it's contents. Adding a dropdown that can choose between other RSS files should be easy if you're using the Flash UI components. Using XMLSA, you could easily make something that first displayed the headlines and then displayed the full story upon click and you'd have a fully fledged news reader.

Click here to download the FLA for this project.

 

 

del.icio.us Favicon Digg Favicon DZone Favicon Reddit Favicon StumbleUpon Favicon Technorati Favicon

 

Casual Games >> << Getting Across to Flash with Java