Archive for the 'XML hacks' Category

My Friend Flickr: pulling Flickr photos into your site with XSLT

Friday, March 17th, 2006

Here’s another fun server-side XSLT (Extensible Stylesheet Language Transformations) hack for you. Previously, I talked about the idea of using RSS for loosely coupled content management. Well, I’ve been wanting to do some Web 2.0 mashup kind of stuff, but given that my XPath skills are a lot sharper these days than my JavaScript and AJAX (Asynchronous JavaScript and XML) skills (I still need to find the time to exercise that part of my brain again), I decided I’d attack them from the server side with PHP and XSL instead of writing some pretty browser-choking client-side applet. And the first target of opportunity was Flickr.

I’ve been wanting to add a live feed of my Flickr photo stream to one of my sites for a while. Fortunately, Flickr provides an Atom 0.3 feed (as well as RSS feeds) for each photo stream, so there was already a well-structured XML source to pull the data from. So, using Dreamweaver’s PHP XSLT library, I created a component that pulls in the Atom feed, strips off the extraneous text that gets put in front of each image, and renders the images from the feed wherever I use a <?php include(’flickr.php’); ?> in the page.

In the Atom feed for Flickr, every item starts with the user name and the text “posted a photo:”. So, I wrote an XSL statement using the “substring-after” function of XSLT to prune off the extraneous text. Then I made sure that the image tags in the feed would render properly by disabling output escaping:

<xsl:value-of select=”substring-after(atom:content,’posted a photo:’)” disable-output-escaping=”yes”/>

I didn’t want every photo in my feed to get displayed, so I used a parameter, “ItemsPerPage”, to control the number of items processed by the XSLT. The parameter makes it possible to select the number of images displayed from the feed at run-time. Alternatively, I could use two parameters to select a window of items to display, and use PHP or Javascript code to page through the feed. (I’ll save that for another project.)

Here’s the full XSL file:


<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp ” “>
<!ENTITY copy “©”>
<!ENTITY reg “®”>
<!ENTITY trade “™”>
<!ENTITY mdash “—”>
<!ENTITY ldquo ““”>
<!ENTITY rdquo “””>
<!ENTITY pound “£”>
<!ENTITY yen “¥”>
<!ENTITY euro “€”>
]>
<xsl:stylesheet version=”1.0″ xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” xmlns:atom=”http://purl.org/atom/ns#” xmlns:dc=”http://purl.org/dc/elements/1.1/”>
<xsl:output method=”html” encoding=”ISO-8859-1″/>
<xsl:param name=”ItemsPerPage” select=”4″ />
<xsl:template match=”/”>
<xsl:for-each select=”atom:feed/atom:entry[position() <= $ItemsPerPage]”>
<p><xsl:value-of select=”substring-after(atom:content,’posted a photo:’disable-output-escaping=”yes”/></p>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

The results of this XSLT can be seen in the right-hand sidebar of the example attention stream page I built in PHP, combining this blog, a del.icio.us feed and Flickr.

Building Blortals with Blogs, RSS feeds, XSL Transforms and Dreamweaver

Friday, March 17th, 2006

For the past month or so, I’ve been busy working deep under the hood here at eWEEK to pull together the worlds of lightweight content management (or, in other words, weblogs) and “enterprise” content management (as in the software guts that drive eWEEK.com) to create a new set of hybrid sites that my colleague Mary Jo Foley jokingly christened “blortals”. They combine the interactive, personal approach of blogs with the stream of news, analysis, opinion and product reviews related to a particular topic from eWEEK and other Ziff publications. And they’re put together almost entirely with RSS and XML Style Language (XSL).

While XML-based client-side browser magic like AJAX is all the rage right now, sometimes simple server-side XML magic is better–especially when you’re dealing with aggregating content from multiple sources, and you want your page to load somewhat faster than continental drift. Besides, syndication formats aren’t just for clients anymore–as the number of applications and services that produce RSS and Atom feeds grow exponentially, the XML syndication formats can provide a quick and easy way to integrate related content from disparate sources. Call it “Loosely-coupled content management.”

For example, take a look at Stan Gibson’s new IBM Watch site. It runs on our weblog server, but it could really run just about anywhere, because almost all of the content is rendered from XSL files that are pointed at RSS feeds from Stan’s weblog, eWEEK.com, and other Ziff sites. In the case of Stan’s site, the inbound IBM news feeds from eWEEK are created by a query against our content management system for any stories where IBM is a related company.

In fact, getting the RSS feeds configured was half the battle. That’s because Adobe’s Macromedia Dreamweaver 8 not only includes a relatively designer-friendly mechanism for adding XSL transforms to dynamic pages, but the actual code components required to do server-side transformations for ColdFusion, ASP, ASP.NET and PHP.

The only real coding I had to do was in XPath language in the XSL files used to define the transforms, to control how many items from each RSS feed are displayed on the page. So, for example, to only get 4 items from a feed, I could just use:
<xsl:for-each select=”rss/channel/item[position() <= 4]”>

</xsl:for-each>

And, since in some cases I was able to re-use existing RSS feeds (for example, the “What Your Boss Is Reading” section of the right sidebar of Stan’s site uses the RSS feeds of Baseline and CIO Insight), I also had to strip out the advertisments that get inserted into those feeds.

Thanks to XPath, that’s not a problem, since I was able to insert conditional statements into the XSL. The ads in our RSS feeds all have “ADV” at the beginning of the title, so all I needed was a conditional statement that skipped items starting with ADV:
<xsl:if test=”not(starts-with(title, ‘ADV’))”>

</xsl:if>

Since I wanted to be able to reuse the XSL fragments I created to render other feeds, and wanted to be able to set the number of items rendered and the advertising test string at the time the RSS feed is rendered, I made those values into parameters. Here’s the XSL fragment I used to render the headlines from an RSS feed, linked to their stories:

<?xml version=”1.0″ encoding=”ISO-8859-1>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp “ ”>
<!ENTITY copy “©”>
<!ENTITY reg “®”>
<!ENTITY trade “™”>
<!ENTITY mdash “—”>
<!ENTITY ldquo ““”>
<!ENTITY rdquo “””>
<!ENTITY pound “£”>
<!ENTITY yen “¥”>
<!ENTITY euro “€”>
]>
<xsl:stylesheet version=”1.0″ xmlns:xsl=”
http://www.w3.org/1999/XSL/Transform” xmlns:wfw=”http://wellformedweb.org/CommentAPI/” xmlns:slash=”http://purl.org/rss/1.0/modules/slash/” xmlns:dc=”http://purl.org/dc/elements/1.1/“>
<xsl:output method=”html” encoding=”ISO-8859-1″/>
<xsl:param name=”ItemsPerPage” select=”4″ />
<xsl:param name=”advertcheck” select=”ADV” />
<xsl:template match=”/”>
<xsl:for-each select=”rss/channel/item[position() <= $ItemsPerPage]”>
<xsl:if test=”not(starts-with(title, $advertcheck))”>
<a href=’{link}’><h3><xsl:value-of select=”title”/></h3></a>
<p><xsl:value-of select=”description” disable-output-escaping=”yes”/></p>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

So, throw five or six transformations onto a dynamic web page, and before you know it you’ve got a portal. As they used to say in the Ronco ads, “It’s just that easy.”

And, since it’s XSL, that means that I can move the pages that render the feeds to any dynamic server platform I want with minimal recoding– to do a proof of concept, I took a site developed on our .NET-based Telligent blog server and ported it over to a Linux box running Apache and PHP in just under 4 minutes.