Hi Jacob is it any particular RSS feed you are trying to consume, such as a Flickr feed or a generic RSS news item feed? I have lost the example I wrote for someone else, however I will try and comble somethign together shortly.
@{var xml = "";
var targetUri = newUri("http://blog.orcare.com/rss");
var request = (HttpWebRequest)WebRequest.Create(targetUri);
if ((request.GetResponse().ContentLength > 0))
{
var stream = newStreamReader(request.GetResponse().GetResponseStream());
xml = stream.ReadToEnd();
if (stream != null)
{
stream.Close();
}
}
var feed = Library.ToDynamicXml(xml);
}@foreach (var post in feed.channel.item)
{
@post.title <br/>
}
The thing to remember is that you're turning the feed into a dynamic object. So "channel.item" is actually the item node in the channel node. Also, in post.title, the "title" is the title node in that "channel.item".
You can do all kinds of fun things with it like @Library.Find and so on (see my examples project and the cheat sheet for more information)
Sebastian's way might be the nicer way to do it, in terms of fetching the item value out using dot noation eg @post.description, @post.title etc However this was the approach I done when I helped out Anders Stentebjerg
@using System.Xml;
@{//Get the XML from remote URLXmlDocument xml = newXmlDocument();
//URL currently hardcoded - but you could use a macro param to pass in URL
xml.Load("http://blog.orcare.com/rss");
//Select the nodes we want to loop throughXmlNodeList nodes = xml.SelectNodes("//item");
//Traverse the entire XML nodes.foreach (XmlNode node in nodes)
{
//Get the value from the <title> nodevar title = node.SelectSingleNode("title").InnerText;
//Get the value from the <description> nodevar description = node.SelectSingleNode("description").InnerText;
<h1>@title</h1>@Html.Raw(description)
}
}
Just a quickie in terms of performance, depending on the size of the RSS feed and where its located (e.g. its usually slower to retrieve a feed from another site that's in another country than it is t get one from the same server/location), you'll want to consider caching. You can either set a high cache rate for the Macro, or you can use the excellent Feed Cache package, which allows you to cache the feed at periodic intervals and you can get your list macro to read from the cached file instead. It reduces the network travel to nothing, and if the RSS feed goes down for any reason, you'll still have the cached copy, so the feed won't just drop off your site!
Anders just sent me the link to the version I sent him a while ago, which is very similar but shows a slightly different approach again, but Tim you make some great points about combining with the Feed Cache package, as you can ensure you wil always have XML to retrieve if the remote site is down.
@using System.Xml.XPath;
@using System.Xml;
@{
//Fetch RSS XML
XmlTextReader udBrudRSS = new XmlTextReader("http://myblog.com/rss");
//Create new XML document
XmlDocument doc = new XmlDocument();
//Load in our remote XML into our XML document
doc.Load(udBrudRSS);
//Select our nodes we want with some xPath
XmlNodeList rssItems = doc.SelectNodes("//item");
}
<ul>
@{
//For each item node we can then ouput what we want
foreach (XmlNode node in rssItems)
{
<li>
<div class="date">@node["pubDate"].InnerText</div>
<a href="@node["link"].InnerText">@node["title"].InnerText</a>
</li>
}
}
</ul>
I am trying to modify your script to limit the number of Items pulled from the feed. I was trying this, but it doesn't like "Take" in this syntax. Can you point me in the right direction? Thanks!
<ul> @{ //For each item node we can then ouput what we want foreach(XmlNode node in rssItems.Take(6)) { <li> <div class="date">@node["pubDate"].InnerText</div> <a href="@node["link"].InnerText">@node["title"].InnerText</a> </li> } } </ul>
Hey Steve, I figured out a solution if you ahve not come up with anything yet. I am not a programmer so I had to do a lot of searching, but here is my solution:
@using System.Xml.XPath;
@using System.Xml;
@{
//Fetch RSS XML
@*
var feedUrl = @Parameter.feedUrl;
var limit = Int32.Parse(@Parameter.setLimit);
*@
var feedUrl = @Model.feedUrl;
var limit = @Model.setLimit;
XmlTextReader udBrudRSS = new XmlTextReader(feedUrl);
//Create new XML document
XmlDocument doc = new XmlDocument();
//Load in our remote XML into our XML document
doc.Load(udBrudRSS);
//Select our nodes we want with some xPath
XmlNodeList rssItems = doc.SelectNodes("//item");
var letsCountNodes = 1;
//For each item node we can then ouput what we want
I know that it has been a long time since the last post but I will show my solution anyway regarding limit the number of Items pulled from the feed.
@inherits umbraco.MacroEngines.DynamicNodeContext
@using System.Xml.XPath; @using System.Xml;
@{ //Fetch RSS XML XmlTextReader udBrudRSS = new XmlTextReader("http://frederikssund.lokalavisen.dk/section/senestenytrss");
//Create new XML document XmlDocument doc = new XmlDocument();
//Load in our remote XML into our XML document doc.Load(udBrudRSS);
//Select our nodes we want with some xPath XmlNodeList rssItems = doc.SelectNodes("//item");
}
@{ //For each item node we can then ouput what we want
var maxItems = 5; var displayCount = rssItems.Count < maxItems ? rssItems.Count : maxItems; for (int index = 0; index < displayCount; index++) { var node = rssItems[index];
This is what I ended up using. A simple if statement to control the number of items in the feed.
@using System.Xml.XPath;
@using System.Xml;
@using umbraco.MacroEngines;
@inherits umbraco.MacroEngines.DynamicNodeContext
@{
//Fetch RSS XML
XmlTextReader udBrudRSS = new XmlTextReader("http://rosestem.rose-hulman.edu/controls/cms_v2/components/rss/rss.aspx?sid=1554&gid=1&calcid=1110&page_id=402");
//Create new XML document
XmlDocument doc = new XmlDocument();
//Load in our remote XML into our XML document
doc.Load(udBrudRSS);
//Select our nodes we want with some xPath
XmlNodeList rssItems = doc.SelectNodes("//item");
}
<ul class="rss-feed">
@{
//For each item node we can then ouput what we want
var i = 0;
foreach (XmlNode node in rssItems)
{
<li>
<a href="@node["link"].InnerText">@node["title"].InnerText</a>
<div class="date">@Html.Raw(@node["description"].InnerText)</div>
</li>
i++;
if (i == 5){ break; }
}
}
</ul>
Hey, something has come up with my feed parser. I was pulling a feed in using:
@{ //Fetch RSS XML XmlTextReader udBrudRSS =newXmlTextReader("http://rosestem.rose-hulman.edu/controls/cms_v2/components/rss/rss.aspx?sid=1554&gid=1&calcid=1110&page_id=402");
//Create new XML document XmlDocument doc =newXmlDocument();
//Load in our remote XML into our XML document doc.Load(udBrudRSS);
//Select our nodes we want with some xPath XmlNodeList rssItems = doc.SelectNodes("//item");
} <ul class="rss-feed"> @{ //For each item node we can then ouput what we want var i =0; foreach(XmlNode node in rssItems) { <li> <a href="@node["link"].InnerText">@node["title"].InnerText</a> <div class="date">@Html.Raw(@node["description"].InnerText)</div>
</li> i++; if (i == 5){ break; } }
}
This code worked until the location of the feed suffered a DOS and changed their firewall set up.
After talking with their IT support department, they suggested adding a "user agent" within the script, but I am unfamiliar with how to do this in razor. Could someone show me how to accomplish this in my current script?
thanks so much for your solution in this thread. I've been using it and it seems to work great most of the time. Sometimes the page throws an error 'server unavailable' pointing to the doc.Load(udBrudRSS); line, and I'm guessing it's because perhaps the rss feed is currently unavailable?
What's the easiest/best syntax to just add a check on that BLOG rss URL? If that URL isn't available/accessible, I would rather have no feed returned than a full page error.
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@using System.Xml.XPath;
@using System.Xml;
@using umbraco.MacroEngines;
@{
//Fetch RSS XML
XmlTextReader udBrudRSS = new XmlTextReader("http://myblogurl/feeds/posts/default?alt=rss");
//Create new XML document
XmlDocument doc = new XmlDocument();
//Load in our remote XML into our XML document
doc.Load(udBrudRSS);
//Select our nodes we want with some xPath
XmlNodeList rssItems = doc.SelectNodes("(//item)[position() <= 3]");
}
<ul class="listicon">
@{
foreach (XmlNode node in rssItems)
{
<li class="blogIcon"><a title="@node["title"].InnerText" href="@node["link"].InnerText" target="_blank" >@node["title"].InnerText</a></li>
}
}
</ul>
Do any of these examples prevent Internet users from seeing what rss feed url's you are pulling (i.e. prevent them from seeing what .rss or .xml files you are using)?
Consume an RSS feed in Razor
Has anyone in the Umbraco community created a script that allows a RSS feed to be consumed an output segments as HTML that we can style?
THANKS!
Hi Jacob is it any particular RSS feed you are trying to consume, such as a Flickr feed or a generic RSS news item feed?
I have lost the example I wrote for someone else, however I will try and comble somethign together shortly.
Warren
Thank you for the response!
It is for a Tumblr RSS feed.
Jacob
Do you have an example to a Tumblr RSS feed URL that I can experiment with and then I can see what I can do.
Warren
Here's a quick & dirty one that works:
The thing to remember is that you're turning the feed into a dynamic object. So "channel.item" is actually the item node in the channel node. Also, in post.title, the "title" is the title node in that "channel.item".
You can do all kinds of fun things with it like @Library.Find and so on (see my examples project and the cheat sheet for more information)
@Warren Buckley
Here's our Tumblr feed: http://blog.orcare.com/rss
Updated my post with that URL, and tested it, still works :-)
Sebastian's way might be the nicer way to do it, in terms of fetching the item value out using dot noation eg @post.description, @post.title etc
However this was the approach I done when I helped out Anders Stentebjerg
Just a quickie in terms of performance, depending on the size of the RSS feed and where its located (e.g. its usually slower to retrieve a feed from another site that's in another country than it is t get one from the same server/location), you'll want to consider caching. You can either set a high cache rate for the Macro, or you can use the excellent Feed Cache package, which allows you to cache the feed at periodic intervals and you can get your list macro to read from the cached file instead. It reduces the network travel to nothing, and if the RSS feed goes down for any reason, you'll still have the cached copy, so the feed won't just drop off your site!
Anders just sent me the link to the version I sent him a while ago, which is very similar but shows a slightly different approach again, but Tim you make some great points about combining with the Feed Cache package, as you can ensure you wil always have XML to retrieve if the remote site is down.
Thanks a lot guys, I will implemet later and let you know if it works or not!
Jacob
Warren,
I am trying to modify your script to limit the number of Items pulled from the feed. I was trying this, but it doesn't like "Take" in this syntax. Can you point me in the right direction? Thanks!
I would like to know how to do this as well, limit the nummber of results. Why does it hate Take()?
Hey Steve, I figured out a solution if you ahve not come up with anything yet. I am not a programmer so I had to do a lot of searching, but here is my solution:
Hi
I know that it has been a long time since the last post but I will show my solution anyway regarding limit the number of Items pulled from the feed.
@inherits umbraco.MacroEngines.DynamicNodeContext
@using System.Xml.XPath;
@using System.Xml;
@{
//Fetch RSS XML
XmlTextReader udBrudRSS = new XmlTextReader("http://frederikssund.lokalavisen.dk/section/senestenytrss");
//Create new XML document
XmlDocument doc = new XmlDocument();
//Load in our remote XML into our XML document
doc.Load(udBrudRSS);
//Select our nodes we want with some xPath
XmlNodeList rssItems = doc.SelectNodes("//item");
}
@{
//For each item node we can then ouput what we want
var maxItems = 5;
var displayCount = rssItems.Count < maxItems ? rssItems.Count : maxItems;
for (int index = 0; index < displayCount; index++)
{
var node = rssItems[index];
<article class="blog-post text-post">
<div class="blog-content">
<div class="title">
<h2><a href="@node["link"].InnerText">@node["title"].InnerText</a></h2>
</div>
<p>@node["description"].InnerText</p>
</div>
</article>
}
}
// René
Thanks Rene,
This is what I ended up using. A simple if statement to control the number of items in the feed.
An alternative solution:
This will now allow you to do:
Sorry, it got posted twice and I don't seem to be able to delete it.
Hi All!
It's a bit late answer, but why not to use XPath to limit scope:
XmlNodeList rssItems = doc.SelectNodes("//item[position() < 5]");
Hey, something has come up with my feed parser. I was pulling a feed in using:
This code worked until the location of the feed suffered a DOS and changed their firewall set up.
After talking with their IT support department, they suggested adding a "user agent" within the script, but I am unfamiliar with how to do this in razor. Could someone show me how to accomplish this in my current script?
Hi Warren,
thanks so much for your solution in this thread. I've been using it and it seems to work great most of the time. Sometimes the page throws an error 'server unavailable' pointing to the doc.Load(udBrudRSS); line, and I'm guessing it's because perhaps the rss feed is currently unavailable?
What's the easiest/best syntax to just add a check on that BLOG rss URL? If that URL isn't available/accessible, I would rather have no feed returned than a full page error.
Hi Brian! You might can try to use Try/Catch, something like:
try
{
doc.Load(udBrudRSS);
}
catch { }
Hi,
Do any of these examples prevent Internet users from seeing what rss feed url's you are pulling (i.e. prevent them from seeing what .rss or .xml files you are using)?
is working on a reply...