BizTalk Utilities CV ,   Jobs ,   Code library
 
Go to the front page to continue learning about XML or select below:

Contents

ReBlogger Contents

Previous posts in WSCF/WCF

 
 
Page 6632 of 20233

Forget about writing Atom or RSS XML handling code ever again

Blogger : Daniel Cazzulino
All posts : All posts by Daniel Cazzulino
Category : WSCF/WCF
Blogged date : 2007 Dec 17

A *very* welcome addition to .NET 3.5, which just went RTM for MSDN subscribers and trial for the rest before general availability early next year: System.ServiceModel.Syndication.

This namespace, which lives in the System.ServiceModel.Web.dll assembly which provides the WCF Syndication functionality, contains useful classes for working with feeds and items. I won't go over the Architecture of Syndication, How the WCF Syndication Object Model Maps to Atom and RSS, How to: Create a Basic RSS Feed, How to: Create a Basic RSS Feed, How to: Expose a Feed as both Atom and RSS or the basics of Syndication Extensibility. All those links provide enough to get you started.

The typical usage is:

 

The only thing I felt was missing was a factory that abstracts me from having to decide which formatter to create for a given source: the factory should be able to determine this automatically depending on the first element of the feed/item.

With the factory in place, reading a feed without caring for its format, is as simple as:

using (XmlReader reader = XmlReader.Create(atomFeedUrl))
{
    SyndicationFeedFormatter formatter = SyndicationFormatterFactory.CreateFeedFormatter(reader);
    formatter.ReadFrom(reader);
    SyndicationFeed feed = formatter.Feed;
}

Note that there's nothing in my code that knows about RSS or Atom.

Processing of the item and extensions is very friendly and quite flexible, making for a very nice platform to base syndication extension processing plugins:

    foreach (SyndicationItem item in feed.Items)
    {
        // ... process item

        foreach (SyndicationElementExtension extension in item.ElementExtensions)
        {
            // ... process extensions
            // example: SSE sync
            if (extension.OuterNamespace == Sync.NamespaceUri)
            {
                // NOTE: we don't need to pass an explicit XmlSerializer because we implement 
                // IXmlSerializable, so the library figures out it needs one :)
                Sync sync = extension.GetObject<Sync>();
                // ... do something with the extension
            }
            else if (extension.OuterName == "Mock")
            {
                // this extension does not implement IXmlSerializable neither is a WCF data 
                // contract, so we need to pass an XmlSerializer
                Mock m = extension.GetObject<Mock>(new XmlSerializer(typeof(Mock)));
                // ... do something with the extension.
            }
        }
    }

So here goes such a factory:

/// <summary>
/// Creates formatters for RSS 2.0 and Atom 1.0 according to the input content.
/// </summary>
/// <remarks> /// <see cref="http://www.clariusconsulting.net/kzu">Created by Daniel Cazzulino.</see> /// </remarks>
public static class SyndicationFormatterFactory { static XmlReaderSettings settings; static SyndicationFormatterFactory() { // Makes the processing faster for the readers we create. settings = new XmlReaderSettings(); settings.IgnoreComments = true; settings.IgnoreProcessingInstructions = true; settings.IgnoreWhitespace = true; settings.CheckCharacters = true; settings.CloseInput = true; } /// <summary> /// Creates a <see cref="SyndicationFeedFormatter"/> according to the /// input format. /// </summary> /// <param name="uriString">Feed location</param> /// <exception cref="NotSupportedException">The input does not contain a valid RSS 2.0 or Atom 1.0 feed.</exception> public static SyndicationFeedFormatter CreateFeedFormatter(string uriString) { using (XmlReader reader = XmlReader.Create(uriString, settings)) return CreateFeedFormatter(reader); } /// <summary> /// Creates a <see cref="SyndicationFeedFormatter"/> according to the /// input format. /// </summary> /// <param name="uri">Feed location</param> /// <exception cref="NotSupportedException">The input does not contain a valid RSS 2.0 or Atom 1.0 feed.</exception> public static SyndicationFeedFormatter CreateFeedFormatter(Uri uri) { using (XmlReader reader = XmlReader.Create(uri.ToString(), settings)) return CreateFeedFormatter(reader); } /// <summary> /// Creates a <see cref="SyndicationFeedFormatter"/> according to the /// input format. /// </summary> /// <param name="reader">Feed source</param> /// <exception cref="NotSupportedException">The input does not contain a valid RSS 2.0 or Atom 1.0 feed.</exception> public static SyndicationFeedFormatter CreateFeedFormatter(XmlReader reader) { if (reader.ReadState == ReadState.Initial) { reader.MoveToContent(); } Rss20FeedFormatter rss = new Rss20FeedFormatter(); if (rss.CanRead(reader)) { return rss; } Atom10FeedFormatter atom = new Atom10FeedFormatter(); if (atom.CanRead(reader)) { return atom; } throw new NotSupportedException("Invalid feed root element: " + reader.Name); } /// <summary> /// Creates a <see cref="SyndicationItemFormatter"/> according to the /// input format. /// </summary> /// <param name="uriString">Item location</param> /// <exception cref="NotSupportedException">The input does not contain a valid RSS 2.0 or Atom 1.0 item.</exception> public static SyndicationItemFormatter CreateItemFormatter(string uriString) { using (XmlReader reader = XmlReader.Create(uriString, settings)) return CreateItemFormatter(reader); } /// <summary> /// Creates a <see cref="SyndicationItemFormatter"/> according to the /// input format. /// </summary> /// <param name="uri">Item location</param> /// <exception cref="NotSupportedException">The input does not contain a valid RSS 2.0 or Atom 1.0 item.</exception> public static SyndicationItemFormatter CreateItemFormatter(Uri uri) { using (XmlReader reader = XmlReader.Create(uri.ToString(), settings)) return CreateItemFormatter(reader); } /// <summary> /// Creates a <see cref="SyndicationItemFormatter"/> according to the /// input format. /// </summary> /// <param name="reader">Item source</param> /// <exception cref="NotSupportedException">The input does not contain a valid RSS 2.0 or Atom 1.0 item.</exception> public static SyndicationItemFormatter CreateItemFormatter(XmlReader reader) { if (reader.ReadState == ReadState.Initial) { reader.MoveToContent(); } Rss20ItemFormatter rss = new Rss20ItemFormatter(); if (rss.CanRead(reader)) { return rss; } Atom10ItemFormatter atom = new Atom10ItemFormatter(); if (atom.CanRead(reader)) { return atom; } throw new NotSupportedException("Invalid item element: " + reader.Name); } }

 

You can also download the plain text representation for easier copying.

 

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.


Read comments or post a reply to : Forget about writing Atom or RSS XML handling code ever again
Page 6632 of 20233

Newest posts
 

    Email TopXML