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.
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.
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.
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.
Figure 4: Context Menu displaying new plug-in.
Click on the plug-in, and you'll see the result shown in figure 5.
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.