Server-Side Mashup Tutorial

Date: 2008-02-17
Author: Mike Amundsen

Abstract

Building read/write HTTP resources w/ Exyus, while cool, is sometimes more than you need. In this article, you'll see how you can use the XmlPageResource to create a read-only (GET/HEAD) resource that can act as a 'mashup' of other content from remote sites. This allows you to publish cache-able resources that include content from multiple HTTP end-points, including your own local content.

You can view the online version of the Server-Side Mashup.

Introduction

Sometimes you want to publish an HTML resource that is a 'mashup' of the contents of several other HTTP resources. A good example is the 'home' page of a web site. It might include the most recent posts to the site's news blog, the list of new members, as well as some home-page static content. Exyus makes creating these mashups easy using the XmlPageResource class. This class is designed to load a single associated XML and XSL document pair. since Exyus supports XInclude and XPointer, the source XML document can contain pointers to other remot resources.

top

Coding the XmlPageResource

code The first step in the process is to define the HTTP resource you plan to publish. For this demo, the URL will be /server-mashup/ serving text/html. The caching will be set to 60 seconds and we'll use validation caching to improve performance, too. That's really all we need.

Here's the entire code for the ServerMashUp class that derives from the base XmlPageResource base class.

// call up the XML and XSL set to do mashup
[UriPattern(@"/server-mashup/\.xcs")]
[MediaTypes("text/html")]
class ServerMashUp : XmlPageResource
{
    public ServerMashUp()
    {
        this.AllowCreateOnPut = false;
        this.AllowDelete = false;
        this.AllowPost = false;
        this.ContentType = "text/html";
        this.LocalMaxAge = 60;
        this.MaxAge = 60;
        this.TemplateXml = "/server-mashup/index.xml";
        this.TemplateXsl = "/server-mashup/index.xsl";
        this.UseValidationCaching = true;
    }
}

That's all we need to compile. Next we need to compose the XML and XSL documents that will produce the output we want to show to users.

top

The XML Content Document

XML The XML content document is the document that details all the data to display on the page. Since we are showing off the 'mashup' abilities of Exyus, our XML will contain some XInclude statements to pull data from other sources. It will also contain some inline content to show you how to that you don't need XInclude to define content.

For this demo, we'll use two remote resources: USGS Earthquake Center. Both sites offer XML-based feeds that we can use. The USGS site uses Atom and the National Geographic site uses RSS.

Below is the complete XML content document we'll need for the demo:

<?xml version="1.0" encoding="utf-8"?>
<root  xmlns:x="http://www.w3.org/2003/XInclude">
  <local>
    <root>
      <h1>Server-Side Mashup w/ XmlPageResource</h1>
    </root>
  </local>
  <nat-geo>
    <x:include href="http://news.nationalgeographic.com/index.rss" />
  </nat-geo>
  <usgs>
    <x:include href="http://earthquake.usgs.gov/eqcenter/catalogs/1day-M2.5.xml"/>
  </usgs>
  <notes>
    <x:include href="/xcs/templates/server-mashup/notes.xml" />
  </notes>
</root>

Note that one of the x:include elemetns points to a local resource (notes.xml). This document contains some supporting XHTML content that will appear within the page. You can also see (in the local element) some inline XHTML content. XML content documents can contain direct content that can be rendered in the transformation. There is no requirement to use x:include to popupate your XML content documents.

Now it's time to create an XSL Transformation that will produce XHTML that can be viewed with a common browser.

top

The XSL Transform Document

XSL In this step, we'll create an XSL transform document that produces valid XHTML. We'll take it in a couple stages to highlight the process.

The Main Template Rule

The main template rule produces the valid HTML document, head and body along with handling the details of calling other template rules to transform the content from the XML document. Here's how the main template rule looks:

<xsl:template match="/">
  <html>
    <head>
      <title>Exus Server-Side Mashup</title>
      <link type="text/css" rel="stylesheet" href="/xcs/files/server-mashup/server-mashup.css"/>
    </head>
    <body>
      <div id="page">
        <div id="header">
          <xsl:copy-of select="//local/root"/>
          <address>
            <strong>Refreshed:</strong>
            <xsl:value-of select="date:format-date(date:date-time(),'yyyy-MM-dd hh:mm:ss')"/>
          </address>
        </div>
        <div id="news">
          <h2>
            <xsl:value-of select="//nat-geo/rss/channel/title" />
          </h2>
          <dl>
            <xsl:apply-templates select="//nat-geo/rss/channel/item" />
          </dl>
        </div>
        <div id="side-bar">
          <div id="notes">
            <xsl:copy-of select="//notes/root"/>
          </div>
          <div id="quakes">
            <h2>
              <xsl:value-of select="//atom:feed/atom:title" />
            </h2>
            <p>
              <xsl:value-of select="//atom:feed/atom:subtitle"/>
            </p>
            <ul>
              <xsl:apply-templates select="//atom:entry" />
            </ul>
          </div>
        </div>
        <hr class="clear"/>
      </div>
    </body>
  </html>
</xsl:template>
			

Transforming the RSS Content

The content from the National Geographic web site is in RSS format. Here's the rule to convert RSS item elements for our page:

<!-- handle national geographic items-->
<xsl:template match="nat-geo/rss/channel/item">
  <dt>
    <a href="{link}" title="{pubDate}" target="_blank">
      <xsl:value-of select="title"/>
    </a>
  </dt>
  <dd>
    <xsl:value-of select="description" disable-output-escaping="yes"/>
  </dd>
</xsl:template>
			

Transforming the Atom Content

the content from the USGS web site is in Atom format. Here's the rule to handle Atom entry elements:

<!-- handle usgs entries -->
<xsl:template match="atom:entry">
  <li>
    <a href="{//atom:feed/@xml:base}{atom:link[@rel='alternate']/@href}" title="{atom:updated}" target="_blank">
      <xsl:value-of select="atom:title"/>
    </a>
  </li>
</xsl:template>
			

That's really all there is. Some additional preamble in the XSL document has been left out here, but you can check out the complete XSL document online.

The only thing left is to spruce up the display using some CSS.

top

Adding CSS Styles

styles We could stop at this point. The demo does what it puports to do - combining multiple HTTP end-points into a single resource. But we must admit, the page looks pretty ugly. Let's add a bit of CSS to give it a better loo-and-feel.

Below is the complete CSS file needed to update the display:

a
{
  color:black;
}
hr.clear
{
  clear: both;
  visibility: hidden;
}
h1, h2, h3, h4, p
{
  margin: 0;
  padding: 0;
}
h2, h3, h4
{
  margin-top: .5em;
}
dt
{
  font-weight: bold;
  margin-bottom: .2em;
}
dd
{
  margin-bottom: .5em;
  margin-left: .3em;
}
img
{
  margin-right: .3em;
  border: 0;
}
ul
{
  margin: 0;
  padding: 0;
  list-style-position: inside;
}
#header
{
  background-color: silver;
  border: 1px solid black;
  padding: .3em;
  margin: -.3em;
}
#page
{
  width: 760px;
  margin: auto;
  background-color: #e6e6e6;
  border: 1px solid silver;
  padding: .3em;
}
#news
{
  width: 400px;
  float: left;
}
#side-bar
{
  width: 300px;
  float: right;
}
#notes
{
  background-color:#eee;
  border: 1px solid silver;
  padding: 0 .3em;
  margin-top:.3em;
  margin-right:-.3em;
}
#notes h2
{
  margin-top:.1em;
}
			

And that's the end. Not so bad, eh?

top

Summary

In this article, you learned how to use the XmlPageResource class to build a 'server-side mashup' that includes content from multiple remote (and local) HTTP end-points. You learned how to use the x:include element in the XML Content Document and how to build the XSL Transform Document to convert the imported content into valid XHTML to display to common browsers. Finally, you added a bit of CSS to improve the look of the demo page.

top

About the Author

Mike Amundsen Mike Amundsen lives and works as a contract programmer in Kentucky, USA. He currently spends most of his time creating and supporting large-scale web sites running under Windows and ASP.NET. In the past, he spent quite a bit of time as a trainer/speaker and was involved in the writing of several books on programming with Microsoft technologies.

top