Home arrow PHP arrow Page 7 - Plugging RDF Content Into Your Web Site With PHP

Back To Class - PHP

A Web site which dynamically updates itself with the latestnews and information? Nope, it's not as far-fetched as it sounds. Asthis article demonstrates, all you need is a little imagination, acouple of free RDF files and some PHP glue.

  1. Plugging RDF Content Into Your Web Site With PHP
  2. Have Content, Will Syndicate
  3. Switching Channels
  4. Fresh Meat
  5. Capture The Flag
  6. Nesting Time
  7. Back To Class
  8. Adding A Little Style
  9. Homework
By: icarus, (c) Melonfire
Rating: starstarstarstarstar / 19
February 27, 2002

print this article


Now, with all this power at your command, why on earth would you want to restrict yourself to just a single RDF feed? As I said earlier, most major sites make snapshots of their content available on a regular basis...and it's fairly simple to plug all these different feeds into your own site. Let's see how.

The first thing to do is modularize the code from the previous example, so that you don't need to repeat it over and over again for every single feed. I'm going to simplify things by packaging it into a class, and including the class file into my final PHP script.

Here's the class:

<? class RDFParser { // // variables // // set up local variables for this class var $currentTag = ""; var $flag = ""; var $count = 0; // this is an associative array of channel data with keys ("title", "link", "description") var $channel = array(); // this is an array of arrays, with each array element representing an <item> // each outer array element is itself an associative array // with keys ("title", "link", "description") var $items = array(); // // methods // // set the name of the RDF file to parse // this is usually a local file // you may set it to a remote file if your PHP build supports URL fopen() function setResource($file) { $this->file = $file; } // parse the RDF file set with setResource() // this populates the $channel and $items arrays function parseResource() { // create parser $this->xp = xml_parser_create(); // set object reference xml_set_object($this->xp, $this); // set handlers and parser options xml_set_element_handler($this->xp, "elementBegin", "elementEnd"); xml_set_character_data_handler($this->xp, "characterData"); xml_parser_set_option($this->xp, XML_OPTION_CASE_FOLDING, TRUE); xml_parser_set_option($this->xp, XML_OPTION_SKIP_WHITE, TRUE); // read XML file if (!($fp = fopen($this->file, "r"))) { die("Could not read $this->file"); } // parse data while ($xml = fread($fp, 4096)) { if (!xml_parse($this->xp, $xml, feof($fp))) { die("XML parser error: " . xml_error_string(xml_get_error_code($this->xp))); } } // destroy parser xml_parser_free($this->xp); } // opening tag handler function elementBegin($parser, $name, $attributes) { $this->currentTag = $name; // set flag if entering <channel> or <item> block if ($name == "ITEM") { $this->flag = 1; } else if ($name == "CHANNEL") { $this->flag = 2; } } // closing tag handler function elementEnd($parser, $name) { $this->currentTag = ""; // set flag if exiting <channel> or <item> block if ($name == "ITEM") { $this->count++; $this->flag = 0; } else if ($name == "CHANNEL") { $this->flag = 0; } } // character data handler function characterData($parser, $data) { $data = trim(htmlspecialchars($data)); if ($this->currentTag == "TITLE" || $this->currentTag == "LINK" || $this->currentTag == "DESCRIPTION") { // add data to $channels[] or $items[] array if ($this->flag == 1) { $this->items[$this->count][strtolower($this->currentTag)] .= $data; } else if ($this->flag == 2) { $this->channel[strtolower($this->currentTag)] .= $data; } } } // return an associative array containing channel information // (the $channel[] array) function getChannelInfo() { return $this->channel; } // return an associative array of arrays containing item information // (the $items[] array) function getItems() { return $this->items; } } ?>
If you're familiar with PHP classes, this should be fairly simple to understand. If you're not, flip forward to the end of this article for a link to a great article on how classes work, and then read the listing above again.

Before we proceed to use this class, I'm going to take a few minutes out to point out one line from it - the call to xml_set_object() above.

Now, how about using this class to actually generate a Web page with multiple content feeds?

<? include("class.RDFParser.php"); // how many items to display in each channel $maxItems = 5; ?> <html> <head> <basefont face="Verdana"> <body> <table width="100%" border="0" cellspacing="5" cellpadding="5"> <tr> <!-- first cell --> <td valign=top align=left> <font size="-1"> <? // get and parse freshmeat.net channel $f = new RDFParser(); $f->setResource("http://www.freshmeat.net/backend/fm-releases.rdf"); $f->parseResource(); $f_channel = $f->getChannelInfo(); $f_items = $f->getItems(); // now format and print it... ?> The latest from <a href=<? echo $f_channel["link"]; ?>><? echo $f_channel["title"]; ?></a> <br> <ul> <? // iterate through items array for ($x=0; $x<$maxItems; $x++) { if (is_array($f_items[$x])) { // print data $item = $f_items[$x]; echo "<li><a href=" . $item["link"] . ">" . $item["title"] . "</a>"; } } ?> </ul> </font> </td> <!-- second cell --> <td align=center width=50%> <i>Primary page content here</i> </td> <!-- third cell --> <td valign=top align=left> <font size="-1"> <? // get and parse slashdot.org channel $s = new RDFParser(); $s->setResource("http://slashdot.org/slashdot.rdf"); $s->parseResource(); $s_channel = $s->getChannelInfo(); $s_items = $s->getItems(); // now format and print it... ?> The latest from <a href=<? echo $s_channel["link"]; ?>><? echo $s_channel["title"]; ?></a> <br> <ul> <? // iterate through items array for ($x=0; $x<$maxItems; $x++) { if (is_array($s_items[$x])) { // print data $item = $s_items[$x]; echo "<li><a href=" . $item["link"] . ">" . $item["title"] . "</a>"; } } ?> </ul> </font> </td> </tr> </table> </body> </head> </html>
This is fairly simple. Once an instance of the class has been instantiated with the "new" keyword,

$f = new RDFParser();
class methods can be used to set the location of the RDF file to be parsed

$f->setResource("http://www.freshmeat.net/backend/fm-releases.rdf"); $f->parseResource();
and to retrieve the $channel and $items arrays for further processing.

<? $f_channel = $f->getChannelInfo(); $f_items = $f->getItems(); ?> The latest from <a href=<? echo $f_channel["link"]; ?>><? echo $f_channel["title"]; ?></a> <br> <ul> <? // iterate through items array for ($x=0; $x<$maxItems; $x++) { if (is_array($f_items[$x])) { // print data $item = $f_items[$x]; echo "<li><a href=" . $item["link"] . ">" . $item["title"] . "</a>"; } } ?> </ul>
Each time you reload the script above, the appropriate RDF files will be fetched from the specified locations, parsed and displayed in the format required.

If you have a high-traffic site, you might find this constant "pull" to be more of a nuisance than anything else, especially if the RDF data in question is not updated all that often. In that case, it might be wise to explore the option of caching the RDF data locally, either by extending the example above to include caching features, or by using a cron job to download a local copy of the latest RDF file to your Web server every couple hours, and using the local copy instead of the "live" one.{mospagebreak title=A Free Lunch} Now, the class I've written above is meant primarily for illustrative purposes, and perhaps for low-traffic sites. If you're looking for something more professional, there are a number of open-source RDF parsers out there which bring additional features (including caching) to the table. Let's look at some examples of how they can be used.

The first of these is the RDF parser class, developed by Stefan Saasen for fase4 and available for free download from http://www.fase4.com/rdf/. This is a very full-featured RDF parser, and includes support for caching and authentication via proxy. Here's an example of how it might be used:

<html> <head> <style type="text/css"> body {font-family: Verdana; font-size: 11px;} .fase4_rdf {font-size: 13px; font-family: Verdana} .fase4_rdf_title {font-size: 13px; font-weight : bolder;} </style> </head> <body> <? // include class include("rdf.class.php"); // instantiate object $rdf = new fase4_rdf; // set number of items to display $rdf->set_max_item(5); // set RDF engine options $rdf->use_dynamic_display(true); $rdf->set_Options( array("image"=>"hidden", "textinput"=>"hidden") ); // parse and display data $rdf->parse_RDF("http://www.freshmeat.net/backend/fm-releases.rdf"); $rdf->finish(); ?> </body> </html>
An option to this is the PHP RDF parser class developed by Jason Williams, available at http://www.nerdzine.net/php_rdf/ . This is a bare-bones PHP class, which exposes a few basic methods, but a large number of properties that you can manipulate to format the processed data to your satisfaction.

<html> <head> <basefont face="Verdana"> </head> <body link="Red" vlink="Red" alink="Red"> <? include("rdf_class.php"); // this needs to be a local file $f = new rdfFile("./fm-releases.rdf"); $f->parse(True); $f->ReturnTable(True, "black", "white", "100%"); ?> </body> </html>
Documentation for both these classes is available on their respective Web sites.

>>> More PHP Articles          >>> More By icarus, (c) Melonfire

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort


- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates


Dev Shed Tutorial Topics: