Building and Using RSS Bandit plugins

RSS Bandit Support for the IBlogExtension
RSS Bandit provides support for plug-ins via the IBlogExtension interface. The interface provides a simple extensibility point for aggregators to be able to hook into 3rd party blogging tools.  To read about the development of this extension, review visit this site.

When you right click a feed item within RSS Bandit, you'll notice the following two menu options Blog This Using W::Bloggar and Email This... as in figure 1.

Context Menu
Figure 1: RSS Item Context Menu.

(you might have others if you already have some plugins installed). Building a plugin that implements the IBlogExtension interface adds an item to the context menu when you right click a feed item. Typically an IBlogExtension adds the ability to post an RSS item to a blog from within RSS Bandit. However, there's no limit to the functionality one can add via a plug-in.

Building an IBlogExtension plug-in
In order to build a plug-in for RSS Bandit, simply reference the blogExtension.dll, implement the IBlogExtension interface, and drop the compiled assembly in the plugins directory within the directory where RSS Bandit is installed.

Walk Through
Sounds easy enough? I'll walk you through building a simple plug-in using Visual Studio .NET 2003.  The plug-in we'll create will simply display the XML content of a feed item when you invoke the plug-in via the context menu. I assume that you are already familiar with building a class library with VS.NET.

After starting up Visual Studio.NET, create a new Class Library project called MyPlugin as in figure 2.

Class Library Project
Figure 2: New Project Dialog

The first thing you'll need to do is add a reference to the blogExtension.dll. There are two ways to obtain this dll. The first is to download a signed version from here. You can also look for the assembly in CVS in the following directory: current_work\Source\RssBandit\bin\blogExtension.dll. As of this writing, the dll has the version 1.1.0.2.

You'll also want to add a reference to System.Windows.Forms.dll.

The IBlogExtension interface is intentionally quite simple. For your information, the source code for the interface is below.

using System;
using System.Xml.XPath ;
using System.Reflection ;
using System.Windows.Forms ;
[assembly:AssemblyKeyFile("public.snk")]
[assembly:AssemblyDelaySign(true)]
[assembly:AssemblyVersion("1.1.0.2")]
namespace Syndication.Extensibility
{
    public interface IBlogExtension
    {
     // Name of plug-in, suitable for display to a user 
     string DisplayName { get; }
        // return true if plug-in has configuration settings
     bool HasConfiguration { get; }
        // Return true if an editing GUI will be shown to the 
     // user when BlogItem is called. In this case, the 
     // aggregator will not display its own editing UI. 
     bool HasEditingGUI { get ; }
     // Display configuration dialog to user, if applicable 
     void Configure(IWin32Window parent);
        // Post item to weblog. If plug-in is going to show a 
     // GUI for editing, it should return true to HasEditingGUI(). 
     void BlogItem(IXPathNavigable rssFragment, bool edited);
    }
}

Rename the Class.cs file to DisplayRawRssItemPlugin.cs and the class to DisplayRawRssItemPlugin. Ensure that the following using statements are at the top of your class.

using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using Syndication.Extensibility;
				
Now make sure your class inherits from IBlogExtension. At this point your code window should look like figure 3.

Code Window
Figure 3: Code Window

Hitting the TAB key will create stub code for each of the methods we'll need to implement. There are three properties to implement and two methods. Let's go over each of the properties first and then the methods.

The first property we'll look at is HasConfiguration. RSS Bandit will check this property to see if your plug-in has its own configuration settings. If true, Rss Bandit will call the Configure method in order to display a dialog to edit the configuration. For our simple plug-in, we won't add any configuration settings to worry about. Thus the implementation looks like

public bool HasConfiguration
{
    get
    {
        return false;
    }
}

The next property we'll look at is HasEditingGUI. RSS Bandit will check this property to see if an editing GUI will be shown when you call the plug-in on a selected blog item. In this case, we're merely going to display the RSS item so we will return false here.

public bool HasEditingGUI
{
    get
    {
        return false;
    }
}

The last property we'll look at is DisplayName. The value of this property will be displayed in the context menu when you right click a blog item. So let's make sure it's informative.

public string DisplayName
{
    get
    {
        return "Display This Item's RSS...";
    }
}

The first method we'll look at is Configure. As mentioned before, if HasConfiguration returns true, RSS Bandit will call the Configure menu in order to display a configuration dialog used to configure the plug-in. It is up to you to implement the dialog, but for this plug-in, we'll do no such thing.

public void Configure(System.Windows.Forms.IWin32Window parent)
{
    //Do Nothing
}

Finally we're ready to implement the workhorse of the plug-in, the BlogItem method. When your plugin is called via the context menu, RSS Bandit will hand this method an rssFragment. The rssFragment is an instance of a class that implements the IXPathNavigable interface. This provides a way to create an instance of XPathNavigator used to navigate over the underlying RSS item's XML via the IXpathNavigable.CreateNavigator method.

The underlying XML will contain the source RSS 2.0 document with all other RSS items removed. If the underlying feed is not RSS 2.0 (for example if the feed is an ATOM feed or an earlier version of RSS) Rss Bandit transforms the feed to RSS 2.0 prior to handing it off to the plugin. Therefore, the fragment will always be formatted as RSS 2.0. Actually displaying the underlying XML takes a bit of coding, but we'll roll up our sleeves and dive right in.

/// <summary>
/// This is the identity stylesheet.
/// </summary>
const string IDENTITY_XSLT = @"<?xml version=""1.0"" ?>" 
	+ @"<xsl:stylesheet xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"" version=""1.0"">"
    + @"<xsl:template match=""/"">"
    + @"<xsl:copy-of select=""*"" />"
    + @"</xsl:template>"
    + @"</xsl:stylesheet>";
public void BlogItem(System.Xml.XPath.IXPathNavigable rssFragment, bool edited)
{
    // Create the XPathNavigator
    XPathNavigator navigator = rssFragment.CreateNavigator();
    // Create an XSL Transform.
    XslTransform transform = new XslTransform();
    XmlDocument stylesheetDoc = new XmlDocument();
    stylesheetDoc.LoadXml(IDENTITY_XSLT);
    transform.Load(stylesheetDoc.CreateNavigator(), null, null);
       // This will hold the result of the transform.
    StringBuilder sb = new StringBuilder();
    XmlTextWriter writer = new XmlTextWriter(new StringWriter(sb));
       transform.Transform(navigator, null, writer, null); //sb should have the result now.
    // Build the display
    string display = "TITLE: " + navigator.Evaluate("string(//item/title/text())");
    display += System.Environment.NewLine + System.Environment.NewLine;
    //Display the underlying XML.
    display += sb.ToString();
    System.Windows.Forms.MessageBox.Show(display);
}

What the above code is doing is building an XSLT transformation XslTransform using the identity stylesheet stored in the constant IDENTITY_XSLT.  The identity stylesheet transforms XML into itself.  The reason I do this is its an easy way to look at the underlying XML of an XPathNavigator since the navigator is a forward only cursor through an underlying XML document and doesn't provide a simple means to get at the actual XML.  Not only that, this demonstrates that you could apply any transformation you would like in your plug-in simply by changing the stylesheet involved.

After building the transform the code calls navigator.Evaluate("string(//item/title/text())"); to retrieve the title of the RSS item. The Evaluate method allows you to selectively pull data from the underlying RSS feed using XPath . Finally I append to the title a couple of new lines and the output from the previous transform and then use the MessageBox.Show method to display a message box containing the output.

The entire plug-in code is listed below.

using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using Syndication.Extensibility;
namespace MyPlugin
{
    /// <summary>
    /// Implements a plug-in to display the raw rss for a feed item.
    /// </summary>
    public class DisplayRawRssItem : IBlogExtension
    {
        public DisplayRawRssItem()
        {}
        #region IBlogExtension Members
        public void BlogItem(System.Xml.XPath.IXPathNavigable rssFragment, bool edited)
        {
            // Create the XPathNavigator
            XPathNavigator navigator = rssFragment.CreateNavigator();
                   // Create an XSL Transform.
            XslTransform transform = new XslTransform();
            XmlDocument stylesheetDoc = new XmlDocument();
            stylesheetDoc.LoadXml(IDENTITY_XSLT);
            transform.Load(stylesheetDoc.CreateNavigator(), null, null);
                       // This will hold the result of the transform.
            StringBuilder sb = new StringBuilder();
            XmlTextWriter writer = new XmlTextWriter(new StringWriter(sb));
                       transform.Transform(navigator, null, writer, null); //sb should have the result now.
            // Build the display
            string display = "TITLE: " + navigator.Evaluate("string(//item/title/text())");
            display += System.Environment.NewLine + System.Environment.NewLine;
            //Display the underlying XML.
            display += sb.ToString();
            System.Windows.Forms.MessageBox.Show(display);
        }
        public bool HasEditingGUI
        {
            get
            {
                return false;
            }
        }
        public string DisplayName
        {
            get
            {
                return "Display This Item's RSS...";
            }
        }
        public void Configure(System.Windows.Forms.IWin32Window parent)
        {
            //Do Nothing
        }
        public bool HasConfiguration
        {
            get
            {
                return false;
            }
        }
        /// <summary>
        /// This is the identity stylesheet.
        /// </summary>
        const string IDENTITY_XSLT = @"<?xml version=""1.0"" ?>" 
                                        + @"<xsl:stylesheet xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"" version=""1.0"">"
                                        + @"<xsl:template match=""/"">"
                                        + @"<xsl:copy-of select=""*"" />"
                                        + @"</xsl:template>"
                                        + @"</xsl:stylesheet>";
        #endregion
    }
}

The next step is to compile the assembly and place the resulting MyPlugin.dll into the plugins directory. Make sure to fully restart RSS Bandit. When it starts up again, it will examine every assembly within the plugins directory searching for types that implement the IBlogExtension interface. Each IBlogExtension derived type it finds will be added to the feed item context menu. As mentioned before, the name displayed in the menu is the value of the DisplayName property. When you right click a feed item, you should see the new plug-in displayed as in figure 4.

Context Menu with new plugin
Figure 4: Context Menu displaying new plug-in.

Click on the plug-in, and you'll see the result shown in figure 5.

Underlying RSS item
Figure 5: Underlying RSS item.

Conclusion
This is a simple plug-in to display an RSS item's underlying xml. However, now you have the tools at your disposal to create much more interesting plug-ins than the one demonstrated here. If you do, please share them with everyone by posting a message in the RSS Bandit IBlogExtension forum.