Zishan Neno
Zishan Neno

Reputation: 2817

Consuming WordPress RSS Feed In ASP.NET

How do I consume my WordPress blog's RSS feed to display my latest blog posts on my homepage? I ran into the following piece of code to do this:

  Function GetRSSFeed(strURL as String) as DataTable
    'Get the XML data
    Dim reader as XmlTextReader = New XmlTextReader(strURL)

    'return a new DataSet
    Dim ds as DataSet = New DataSet()
    ds.ReadXml(reader)    
    Return ds.Tables(2)
  End Function

But it errors out at this line: 'ds.ReadXml(reader)' with the following error:

A column named 'comments' already belongs to this DataTable.

Perhaps it doesn't work since this code is from 2003? Does anyone have a working code sample? Many thanks in advance!

Upvotes: 6

Views: 7681

Answers (6)

Christophe Geers
Christophe Geers

Reputation: 8962

You can use LINQ to XML to read a WordPress RSS feed.

First get the feed. Make a Uri instance out of it.

var rssFeed = new Uri("https://github.com/geersch/feed/");

Then perform a GET request.

var request = (HttpWebRequest) WebRequest.Create(rssFeed);
request.Method = "GET";
var response = (HttpWebResponse) request.GetResponse();

Get the response stream and read it to download the contents of the feed.

using (var reader = new StreamReader(response.GetResponseStream()))
{
    var feedContents = reader.ReadToEnd();
    //...
}

Still within the above using statement use LINQ to XML to parse the downloaded content and extract the information you need.

var document = XDocument.Parse(feedContents);

var posts = (from p in document.Descendants("item")
             select new
             {
                 Title = p.Element("title").Value,
                 Link = p.Element("link").Value,
                 Comments = p.Element("comments").Value,
                 PubDate = DateTime.Parse(p.Element("pubDate").Value)
             }).ToList();

Now you can iterate over the results.

foreach(var post in posts)
{
    Console.WriteLine(post.Title);
    Console.WriteLine(post.Link);
    Console.WriteLine(post.Comments);
    Console.WriteLine(post.PubDate);
}

Here I just used an anonymous type to capture the output in, but feel free to create your own BlogPost class or something similar which you can use in the LINQ query.

I'm used to C#, so that's why I've used it in my reply. But you can easily convert it. There are some online converters which you can use.

Regarding your issue with the DataSet (which I personally would not use to implement this), it is caused by an item (blog post) having nodes with the same name.

For example:

<comments>...</comments>
<slash:comments>5</slash:comments>

Sure the second one has a different namespace (slash), but DataSet's ReadXml(...) method does not care about namespaces. It tries to create a second column named "comments". That is why you get the exception.

You can still use a DataSet / DataTable if you want to. Just extract the data from the feed using LINQ to XML as shown above.

Then create a DataSet and add a new table to it.

var dataSet = new DataSet();
var blog = new DataTable("Blog");
blog.Columns.Add("Title", typeof(string));
blog.Columns.Add("Link", typeof(string));
blog.Columns.Add("Comments", typeof(string));
dataSet.Tables.Add(blog);

Iterate over the extracted data and add it to the DataTable:

foreach (var post in posts)
{
    var newRow = blog.NewRow();
    newRow["Title"] = post.Title;
    newRow["Link"] = post.Link;
    newRow["Comments"] = post.Comments;

    blog.Rows.Add(newRow);
 }

Voila, we've now fixed your issue by no longer relying on the DataSet's ReadXml(...) method. Download the feed, extract the data you are interested in and persist it.

Upvotes: 20

Marco
Marco

Reputation: 21

You can use my Library for this: wprssapi.marcogriep.de

Just a few lines of code. Very easy to do:

//Get an Instance of Wordpress Controller (Singleton)
                WordPressFeedController wp = WordPressFeedController.Instance;

                //Load all the RSS Articles
                wp.LoadRSS("http://www.its-all-about.de/rss");

                //Get the Newest Article (Check Docs for other functions)
                var rssItem = wp.GetNewestItem();

                this.label1.Text = rssItem.Title;

                //Text Only, Remove all the HTML Tags - Limit too 300 Chars
                this.richTextBox1.Text = wp.RemoveHTMLFromText(rssItem.Summary.Substring(0, 300)) + "...";

                //Open RSS Article on Button Click
                this.button1.Click += (s, e) => {
                    Process.Start(rssItem.Id);
                };

Upvotes: 0

techchris427
techchris427

Reputation: 1

This is what I use for my wordpress feed reader.

private async void ReadFeed() {
    var rssFeed = new Uri("http://truestrengthmd.com/category/blog/feed");

    var request = (HttpWebRequest)WebRequest.Create(rssFeed);
    request.Method = "GET";
    var _response = await request.GetResponseAsync();
    var response = (HttpWebResponse)_response;

    using (var reader = new StreamReader(response.GetResponseStream()))
    {
        var feedContents = reader.ReadToEnd();

        var document = XDocument.Parse(feedContents);

        var posts = (from p in document.Descendants("item")
                     select new
                     {
                         Title = p.Element("title").Value
                     }).ToList();

        foreach (var post in posts)
        {
            Debug.WriteLine(post.Title);
        }
    }
}

Upvotes: 0

Sean Kendle
Sean Kendle

Reputation: 3609

This is simply @Christophe Geers's great solution converted to VB, as a function:

Protected Function getWordPressFeed(ByVal strUrl As String) As DataTable

    Dim rssFeed = New Uri(strUrl)
    Dim request = DirectCast(WebRequest.Create(rssFeed), HttpWebRequest)
    request.Method = "GET"
    Dim response = DirectCast(request.GetResponse(), HttpWebResponse)
    Dim feedContents As String
    Using reader = New StreamReader(response.GetResponseStream())
        feedContents = reader.ReadToEnd()
    End Using
    Dim document = XDocument.Parse(feedContents)

    Static Dim dcNamespace As XNamespace
    dcNamespace = "http://purl.org/dc/elements/1.1/"

    Dim posts = (From p In document.Descendants("item") Select New With { _
        Key .Title = p.Element("title").Value, _
        Key .Link = p.Element("link").Value, _
        Key .Author = p.Element(dcNamespace + "creator").Value, _
        Key .Description = p.Element("description").Value, _
        Key .PubDate = DateTime.Parse(p.Element("pubDate").Value) _
    }).ToList()

    Dim dataSet = New DataSet()
    Dim blog = New DataTable("Blog")
    blog.Columns.Add("Title", GetType(String))
    blog.Columns.Add("Link", GetType(String))
    blog.Columns.Add("Description", GetType(String))
    blog.Columns.Add("Author", GetType(String))
    blog.Columns.Add("PubDate", GetType(DateTime))

    dataSet.Tables.Add(blog)
    For Each post In posts
        Dim newRow = blog.NewRow()
        newRow("Title") = post.Title
        newRow("Link") = post.Link
        newRow("Description") = post.Description
        newRow("Author") = post.Author
        newRow("PubDate") = post.PubDate
        blog.Rows.Add(newRow)
    Next

    Return blog

End Function

Upvotes: 0

Wiktor Zychla
Wiktor Zychla

Reputation: 48230

I would start in the System.ServiceModel.Syndication namespace, there are classes to directly manipulate RSS feeds. In particular, this looks promising:

 XmlReader reader = XmlReader.Create("http://your.uri.here/feed.xml");
 SyndicationFeed feed = SyndicationFeed.Load(reader);

Then explore the SyndicationFeed class, in particular the Items collection should contain the RSS entries.

Upvotes: 6

Anders Forsgren
Anders Forsgren

Reputation: 11101

I'd start off with the built in classes for RSS/Atom: SyndicationFeed

using (XmlReader reader = XmlReader.Create(url))
{
    return SyndicationFeed.Load(reader);
}  

Upvotes: 3

Related Questions