|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionNamespacesThe The
IdeaRSS and OPML documents are XML documents, basically it's all about XML. The main code will parse XML files and store the gained data somewhere. Somewhere? I guess it would be nice straight forward if I could use data binding, IntelliSense and an intuitive class model to deal with these kind of documents. The worst you can do is implement your XML parser directly into a UI control. But at the end of the day, we would like to present our data in a nice UI. So we have to consume the XML and display the containing data in a nice way. Like always, we should separate data from UI. That's where this framework comes in... DesignCommon
Persistent ManagerBoth document types implement the persistence manager interface. So if you are familiar with the interface methods, you can work with both document types. Basically, this interface is responsible to save, publish and transform the data.
Dirty StateEvery class provides a XML ParserThe main work was to write the parser. Because XML files are read non cached and only forward (performance issue), it's a little bit tricky. The main purpose was to be able to read every well formatted RSS 2.0 feed. No matter which element order or which elements really exist in the XML file. The most code I found on the net parse the XML file with an expected element order, or does support just a few elements. Every class type in the framework supports two constructors. The standard
constructor has no parameters and initializes the class instance with default
values. The second uses an Initialize a new instance of the public RssCloud();
public RssCloud(XmlTextReader);
The implementation depends on the element type. Both parser work modes are based on the idea to read forward and find the corresponding properties on the current class instance via reflection. Most elements contain public RssImage(XmlTextReader xmlTextReader)
{
System.Diagnostics.Debug.Assert(!xmlTextReader.IsEmptyElement);
System.Reflection.PropertyInfo propertyInfo = null;
while(!(xmlTextReader.Name == "image" && xmlTextReader.NodeType ==
XmlNodeType.EndElement))
{
// Continue read
xmlTextReader.Read();
// find related property by name
propertyInfo = GetType().GetProperty(xmlTextReader.Name,
System.Reflection.BindingFlags.IgnoreCase |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance);
if(propertyInfo!=null)
{
// set related property with data
xmlTextReader.Read();
propertyInfo.SetValue(this, xmlTextReader.Value,null);
}
// read till end tag
while(xmlTextReader.NodeType!=XmlNodeType.EndElement)
{
xmlTextReader.Read();
}
}
}
Otherwise they contain public RssCloud(XmlTextReader xmlTextReader)
{
if(!xmlTextReader.HasAttributes) return;
System.Reflection.PropertyInfo propertyInfo = null;
//
while(xmlTextReader.MoveToNextAttribute())
{
// find related property by name
propertyInfo = GetType().GetProperty(xmlTextReader.Name,
System.Reflection.BindingFlags.IgnoreCase |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance);
if(propertyInfo!=null)
{
// set related property with data
propertyInfo.SetValue(this, xmlTextReader.Value,null);
}
}
}
RSSRSS is a web content syndication format. Its name is an acronym for Really Simple Syndication. RSS is a dialect of XML. All RSS files must conform to the XML 1.0 specification, as published on the World Wide Web Consortium (W3C) website. At the top level, a RSS document is a RSS element, with a mandatory attribute called version, that specifies the version of RSS that the document conforms to. Subordinate to the RSS element is a single channel element, which contains information about the channel (metadata) and its contents.
// create channel
RssChannel myChannel = new RssChannel();
myChannel.Title = "Sample Feed";
myChannel.Copyright = "email@adress.com";
myChannel.TTL = 20;
// create item
RssItem myRssItem = new RssItem();
myRssItem.Title = "Sample Rss Item";
myRssItem.Link = "http://www.codeproject.com";
myRssItem.Source.Url = "http://www.codeproject.com";
myRssItem.Source.Value = "Codeproject";
// add item
myChannel.Items.Add(myRssItem);
// save feed
myChannel.Save(@"c:\samplefeed.xml");
OPMLThe purpose of this format is to provide a way to exchange information between outliners and Internet services that can be browsed or controlled through an outliner. The design goal is to have a transparently simple, self-documenting, extensible and human readable format that's capable of representing a wide variety of data that's easily browsed and edited. As the format evolves, this goal will be preserved. It should be possible for a reasonably technical person to fully understand the format with a quick read of a single Web page. It's an open format, meaning that other outliner vendors and service developers are free to use the format to be compatible with Radio UserLand or for any other purpose.
// create document
OpmlDocument myDocument = new OpmlDocument();
myDocument.Head.Title = "Sample document";
myDocument.Head.OwnerEmail = "email@adress.com";
myDocument.Head.OwnerName = "Chris";
// create outline
OpmlOutline myOutlineItem = new OpmlOutline();
myOutlineItem.Text = "Sample Item";
myOutlineItem.Description = "RTFM";
myOutlineItem.XmlUrl = "http://www.codeproject.com/rss.xml";
myOutlineItem.HtmlUrl = "http://www.codeproject.com";
myOutlineItem.IsBreakpoint = false;
myOutlineItem.IsComment = false;
// create sub item
OpmlOutline mySubOutlineItem = new OpmlOutline();
mySubOutlineItem.Text = "Sample Child Item";
// add sub item to item
myOutlineItem.Items.Add(mySubOutlineItem);
// add outline to document
myDocument.Body.Items.Add(myOutlineItem);
// save opml
myDocument.Save(@"c:\sample.opml");
Using the codeThe following samples deal with the RSS classes, but for OPML, it's similar
because the operations are mostly based on the Consume content from InternetThis sample shows how to consume The Code Project "Last 10 updates (category: All Topics)" RSS feed. Uri uri = new
Uri("http://www.codeproject.com/webservices/articlerss.aspx?cat=1");
RssChannel myRssChannel = new RssChannel(uri);
// write the channel title to the standard output stream.
System.Console.WriteLine(myRssChannel.Title);
// write each item's title to the standard output stream.
foreach(Raccoom.Xml.RssItem item in myRssChannel.Items)
{
System.Console.WriteLine(item.Title);
}
This sample shows how to create and save RSS feeds to the local storage. Raccoom.Xml.RssChannel myRssChannel = new Raccoom.Xml.RssChannel();
myRssChannel.Title = "Sample rss feed";
myRssChannel.Copyright = "(c) 2003 by Christoph Richner";
// add item to channel
Raccoom.Xml.RssItem item = new Raccoom.Xml.RssItem();
item.Title = "Raccoom RSS 2.0 Framework announced";
item.Link = "http://jerrymaguire.sytes.net";
myRssChannel.Items.Add(item);
Save feedsThis sample shows different ways to store the feed. // save feed to local storage
myRssChannel.Save(@"c:\cp.xml");
// upload feed to web server
myRssChannel.Publish(new Uri("http://www.mydomain.net"),
"POST", "domain", "username", "password");
// create stream
System.IO.MemoryStream stream = new System.IO.MemoryStream();
myRssChannel.Write(stream);
stream.Close();
Transform feedsThis sample shows how to consume and transform (XSLT/CSS) The Code Project feed. // consume rss feed
Uri uri = new
Uri("http://www.codeproject.com/webservices/articlerss.aspx?cat=1");
RssChannel myChannel = new RssChannel(uri);
// transform to stream
System.IO.MemoryStream memoryStream =
myChannel.Transform(new System.Xml.XmlTextReader("transform.xslt"));
// transform to html output file
myChannel.Transform(new System.Xml.XmlTextReader("transform.xslt"),
"myChannel.htm");
// transform to html and xml output file
myChannel.Transform(new System.Xml.XmlTextReader("transform.xslt"),
"channel.xml", "channel.htm");
EditorsIntroductionThere is an MDI parent form which can hold any number of child forms. The child forms represent the document types, RSS and OPML. The editor provides a most recently used menu and common dialogs for save, open and publish operations. The built-in preview windows are docked using Magic Library and my Docking Manager Extender component which are provided in release mode assemblies.
Type ConvertersIf you like to create well formatted documents which pass successfully the
specification validators, you have to bear in mind that also the input must be
valid. Here I present some type converters to edit kind of tricky values like
RFC
IsoCodeUITypeConverter Inherits from
RfcDateUITypeEditor Inherits from To format a string rfcDateFormat = myDateTime.ToString("r");
SkipDayUITypeConverter Inherits from Drag'n'Drop hyperlink from browser to .NET ControlTo allow drag'n'drop operations, you have to set We only allow dragging if the dragged data is
/// <summary>
/// Allow dragging of UniformResourceLocator (Hyperlinks)
/// </summary>
private void OnDragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{
if(e.Data.GetData("UniformResourceLocator",true)!=null)
{
e.Effect = DragDropEffects.Link;
}
else
{
e.Effect = DragDropEffects.None;
}
}
Now that the user has released the left mouse button, we can get the
/// <summary>
/// If valid UniformResourceLocator was dropped, get it
/// </summary>
private void OnDragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
string hyperLinkUrl = null;
string hyperLinkText = null,
//
try
{
hyperLinkUrl = e.Data.GetData(typeof(string)) as string;
// some browser deliver url and text
// in UniformResourceLocator (Firebird)
string[] tokens = hyperLinkUrl.Split('\\');
if(tokens.Length>1)
{
hyperLinkUrl = tokens[0];
hyperLinkText = tokens[1];
}
// we have to read FILEGROUPDESCRIPTOR to get the text (IE)
else
{
System.IO.Stream ioStream=
(System.IO.Stream)e.Data.GetData("FileGroupDescriptor");
byte[] contents = new Byte[512];
ioStream.Read(contents,0,512);
ioStream.Close();
System.Text.StringBuilder sb = new System.Text.StringBuilder();
//The magic number 76 is the size of that part of the
//FILEGROUPDESCRIPTOR structure before
// the filename starts - cribbed
//from another usenet post.
for (int i=76; contents[i] != 0; i++)
{
sb.Append((char)contents[i]);
}
if (!sb.ToString(sb.Length-4,4).ToLower().Equals(".url"))
{
throw new Exception("filename does not end in '.url'");
}
hyperLinkText = sb.ToString(0,sb.Length-4);
}
// do what ever you wanna do with the hyperlink
this.BeginInvoke(.....)
}
catch (System.Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
ConclusionsFeel free to use this framework in your application. Any feedback or criticism is appreciated. Links
BlogsHistory
Have phun... | ||||||||||||||||||||