Tag Archives: rss

Publicado en : Informática

These days I’m dealing with Apache Wicket and RSS, trying to find a nice way to create a syndication feed that serves part of the content that users can view in the browser (so the content of the articles is HTML).

The mentioned style does not refer here to the embedded HTML (the one within the <content> section of the <entry>s) but to the <content>, <description>, <channel>… tags themselves).

To generate the RSS content I’ve used a trick that simulates a request to the server, leading Wicket to go through the whole request cycle and to render the HTML, which you finally get into a String variable. But that’s a (-n important, I know) matter of another post. By now, let’s just assume that we have a way to get that HTML content, or simply ignore that the content of the articles is HTML.

Well, if you have ever played with Rome you’ll know that, after creating your entries, the “end product” you get is a Feed instance. That’s our entry point. Let’s suppose that we want to serve that feed in a URL like, for instance, http://myserver.com/feeds/myfeed. As when serving JSON, the solution involves creating a custom implementation of IRequestTarget that writes the correct output and content type.

When extending IRequestTarget we must override the respond(RequestCycle requestCycle) method. And it’s there where we must do all the “magic”. Let’s assume that its constructor receives a Feed instance as parameter, and it will keep reference to it as a private variable. The first thing we do is to set the character encoding and the content type, to let the clients to recognize what kind of content they are fetching. Remember, once you have the Feed instance, serving RSS is the same as serving a simple XML. To style the feed, you’ll have to have a CSS or XSL somewhere that are the RSS stylesheets. We will write the RSS processing instructions that will make readers to include those stylesheets and apply them to the feed. For that we must use the WireFeedOutput instead of the common SyndFeedOutput (as I read in http://cephas.net/blog/2006/08/30/xsl-css-processing-instructions-using-rome/). Finally we write to the response output stream, obtained from the Wicket Response) and remember to bind the session if you need to.

public class RSSRequestTarget implements IRequestTarget {

 private SyndFeed feed;

 public RSSRequestTarget(SyndFeed feed) {
   this.feed = feed;
 }

 @Override
 public void respond(RequestCycle requestCycle) {
   requestCycle.getResponse().setCharacterEncoding("UTF-8");
   requestCycle.getResponse().setContentType("text/xml; charset=UTF-8");
   try {
     Writer writer = new OutputStreamWriter(requestCycle.getResponse().getOutputStream());
     WireFeedOutput feedOutput = new WireFeedOutput();
     Document doc = feedOutput.outputJDom(this.feed.createWireFeed());

     // create the XSL processing instruction
     Map<String, String> xsl = new HashMap<String, String>();
     xsl.put("href", "http://myserver.com/xsl/rss.xsl");
     xsl.put("type", "text/xsl");
     xsl.put("media", "screen");
     ProcessingInstruction pXsl = new ProcessingInstruction("xml-stylesheet", xsl);
     doc.addContent(0, pXsl);
<pre>     // create the CSS processing instruction
     Map<String, String> css = new HashMap<String, String>();
     css.put("href", "http://myserver.com/css/rss.css");
     css.put("type", "text/css");
     css.put("media", "screen");
     ProcessingInstruction pCss = new ProcessingInstruction("xml-stylesheet", css);
     doc.addContent(1, pCss);
</pre>
// response
 XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
 outputter.output(doc, writer);
 } catch (IOException e) {
 e.printStackTrace();
 } catch (FeedException e) {
 e.printStackTrace();
 }
 if (MyAppSession.get().getId() == null) {
 MyAppSession.get().bind();
 }

}

So, to use it in a WebPage, extend it as you’re used to do in Wicket, and at some point in the Page constructor, tell it to use our new IRequestTarget implementation (don’t forget to establish that we don’t need associated markup):

 public MyFeedPage extends WebPage {

  public MyFeedPage(PageParameters pageParameters) {
    [...]
    SyndFeed feed = new SyndFeedImpl();
    [...]
    getRequestCycle().setRequestTarget(new RSSRequestTarget(feed));
  }

  @Override
  public boolean hasAssociatedMarkup() {
    return false;
  }
}

Finally, in the init() method of your WebApplication class, mount the feed in your desired URL:

  [...]
  mountBookmarkablePage("/feed/myfeed", XXXPage.class);
  [...]

If you look at the generated feed you’ll see that the first lines look something like:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="http://myserver/xsl/rss.xsl"?>
<?xml-stylesheet type="text/css" media="screen" href="http://myserver/css/layout.css"?>

that are the processing instructions that make it possible to style your feed contents.

Please remember that most of web browsers will somewhat ignore these styles, but not all of them. And there are some RSS client applications that apply the styles when displaying them (think of Feedburner feeds viewer).

As I said, in my case I’m serving HTML content, which I obtain mock-mocking the Wicket request cycle internally. I’ll try to publish something about it.

Post to Twitter Post to Facebook