Mohammed Hoque
Mohammed Hoque

Reputation: 11

Sitecore Custom RSS Feed

I am trying to create a custom RSS feed for my project. I am fairly new to making changes with RSS Feed. So i was reading articles by John West and how to override my RSS by creating a new template and adding my namespace, assembly under extension in my new rss template. But i couldn't make much progress. I need a view something similar to below and the out of the box sitecore rss doesn't do that. Do i have to override the PublicFeed class and "FeedDeliveryLayout.aspx" layout to achieve this? Anyone have any examples that i can look at or any information would be really helpful. Also how do i get the category of the articles to show up in RSS and facet by the category title?

Thanks

<rss xmlns:content="purl.org/.../" xmlns:dc="purl.org/.../" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="purl.org/.../" version="2.0">
<channel>
<title>Blog</title>
<atom:link href="http://mysite/blog/rss" rel="self" type="application/rss+xml"/>
<link>mysite/.../link>
<description>Article Descript</description>
<language>en-US</language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<item>
<title>Article Title</title>
<link>
mysite/.../link>
<category>Sales</category>
<category>Management</category>
<category>Professional</category>
<category>Marketing</category>
<category>Dynamics</category>
<guid isPermaLink="false">mysite/.../guid>
<description>
<p>Article Summary</p> <p>&#160;</p>
</description>
<dc:creator>John Smith</dc:creator>
<pubDate>Wed, 10 Jan 2018 12:00:00 -0400</pubDate>
<content:encoded>
<div class="row"><div><p>BODY OF ARTICLE</p></div>
</content:encoded>
</item>

---Ans-- Modify the feeddeliverylayout.aspx that can be found in sitecore/shell/applications/feeds

 /// <summary>
    /// Parse PublicFeed response (string) convert it into XML document
    /// add/remove/update Node(s) as per requiremnt
    /// </summary>
    /// <param name="html"></param>
    /// <returns>modified Feeds</returns>
    private string ModifyRss(string html)
    {
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(html);
        XmlNodeList items = doc.SelectNodes("//item");

        foreach (XmlNode item in items)
        {
            XmlNode idNode = item.ChildNodes[0];
            XmlNode linkNode = item.ChildNodes[1];
            XmlNode titleNode = item.ChildNodes[2];
            XmlNode descNode = item.ChildNodes[3];
            XmlNode pubDateNode = item.ChildNodes[4];

            item.InsertBefore(titleNode, idNode);
            item.InsertBefore(linkNode, idNode);

            string id = idNode.InnerText;

            Sitecore.Data.Items.Item contextItem = Sitecore.Context.Database.Items[new Sitecore.Data.ID(id)];

            if (contextItem != null)
            {
                // render categories
                var categoriesValue = contextItem[BlogSyndicationRSS.BlogsCategories];

                if (!string.IsNullOrEmpty(categoriesValue))
                {
                    MultilistField refMultilistField = contextItem.Fields[BlogSyndicationRSS.BlogsCategories];
                    if (refMultilistField != null)
                    {
                        Item[] categories = refMultilistField.GetItems();
                        List<Item> check = categories.Where(x => x != null && x.Versions.Count > 0).ToList();

                        if (check != null && check.Count > 0)
                        {
                            Boolean firstCategory = true;

                            foreach (var category in categories)
                            {
                                XmlElement cateogryField = doc.CreateElement("category");
                                cateogryField.InnerText = !string.IsNullOrEmpty(category["TITLE"]) ? category["TITLE"] : category.Name;

                                if (firstCategory)
                                    item.InsertAfter(cateogryField, linkNode);
                                else
                                    item.AppendChild(cateogryField);
                            }
                        }
                    }
                }

                // render creator aka author name
                var createdBy = contextItem[BlogSyndicationRSS.Author];

                if (!string.IsNullOrEmpty(createdBy))
                {
                    XmlElement createdByField = doc.CreateElement("dc", "creator", "urn:abc");
                    createdByField.InnerText = createdBy;
                    item.InsertAfter(createdByField, descNode);
                }

                // render content aka body of blog article
                var body = contextItem[BlogSyndicationRSS.Content];

                if (!string.IsNullOrEmpty(body))
                {
                    XmlElement bodyField = doc.CreateElement("content", "encoded", "urn:abc");
                    bodyField.InnerText = body + GetContentFooter(contextItem);
                    item.InsertAfter(bodyField, pubDateNode);
                }

            }

            var options = LinkManager.GetDefaultUrlOptions();
            options.AlwaysIncludeServerUrl = true;

            idNode.InnerText = LinkManager.GetItemUrl(contextItem, options);
        }

        ProcessXML(doc);

        //remove invalid attributes from xml tags
        var invalidAttributes = "xmlns:atom=\"urn:abc\", xmlns:sy=\"urn:abc\", xmlns:dc=\"urn:abc\", xmlns:content=\"urn:abc\"";
        var outerXML = doc.OuterXml;

        foreach (var invalidAttr in invalidAttributes.Split(','))
        {
            outerXML = outerXML.Replace(invalidAttr, string.Empty);
        }

        return outerXML;

    }

    /// <summary>
    /// Process XMLDocument //rss node to remove existing elements and add new elements
    /// </summary>
    /// <param name="doc"></param>
    private void ProcessXML(XmlDocument doc)
    {
        if (doc != null)
        {
            XmlNode Node = doc.SelectSingleNode("//rss");
            Node.Attributes.RemoveAll();
            AddRemoveAttributes(doc, Node, "xmlns:content", "http://purl.org/rss/1.0/modules/content/");
            AddRemoveAttributes(doc, Node, "xmlns:dc", "http://purl.org/dc/elements/1.1/");
            AddRemoveAttributes(doc, Node, "xmlns:atom", "http://www.w3.org/2005/Atom");
            AddRemoveAttributes(doc, Node, "xmlns:sy", "http://purl.org/rss/1.0/modules/syndication/");
            AddRemoveAttributes(doc, Node, "version", "2.0");

            var updateFrequencyValue = updateFrequency();
            AddElements(doc, "sy:updateFrequency", updateFrequencyValue, "language");
            var updatePeriodValue = updatePeriod();
            AddElements(doc, "sy:updatePeriod", updatePeriodValue, "language");
            var atomLink = AddElements(doc, "atom:link", string.Empty, "title");

            if (atomLink != null)
            {
                atomLink.Attributes.RemoveAll();

                var contextItem = Sitecore.Context.Item.Parent;

                AddRemoveAttributes(doc, atomLink, "href", LinkManager.GetItemUrl(contextItem, new UrlOptions { AlwaysIncludeServerUrl = true }));
                AddRemoveAttributes(doc, atomLink, "rel", "self");
                AddRemoveAttributes(doc, atomLink, "type", "application/rss+xml");
            }
        }
    }


    /// <summary>
    /// Add remove attributs from node
    /// </summary>
    /// <param name="doc">XmlDocument</param>
    /// <param name="Node">Xml Node</param>
    /// <param name="type">type of Attribute</param>
    /// <param name="value">value of Attribute</param>
    private void AddRemoveAttributes(XmlDocument doc, XmlNode Node, string type, string value)
    {
        if (Node != null)
        {
            XmlAttribute typeAttr = doc.CreateAttribute(type);

            typeAttr.Value = value;

            Node.Attributes.Append(typeAttr);
        }
    }

    /// <summary>
    /// Add element to XMLDocument
    /// </summary>
    /// <param name="doc">xml document</param>
    /// <param name="name">element name</param>
    /// <param name="value">elemnent value</param>
    /// <param name="insertAfter">existing node name the new element will be inserted after</param>
    /// <returns></returns>
    private XmlNode AddElements(XmlDocument doc, string name, string value, string insertAfter)
    {
        XmlNode Node = doc.SelectSingleNode("//channel");

        XmlNode newElement = doc.CreateNode(XmlNodeType.Element, name, "urn:abc");
        newElement.InnerText = value;
        Node.InsertAfter(newElement, doc.SelectSingleNode("//" + insertAfter));

        return newElement;
    }

Upvotes: 1

Views: 918

Answers (2)

arul pushpam
arul pushpam

Reputation: 561

Add data to fields of the feed Developers can manually set fields on the SyndicationItem in their custom RenderItem method. A complete (if simple) example:

namespace SitecoreSpark.Feature.RSS{
public class CustomNewsFeed : PublicFeed
{
    protected override SyndicationItem RenderItem(Item item)
    {
        SyndicationItem syndicationItem = base.RenderItem(item);

        // Ensure that we only render items that we expect (can alternatively override the 'ShouldItemBeIncludedInFeed' method)
        if (item.TemplateName == "Webpage")
        {
            // Assign a custom title, description, and date
            syndicationItem.Title = new TextSyndicationContent(item["Page Title"], TextSyndicationContentKind.Html);
            syndicationItem.Summary = new TextSyndicationContent(item["Article Description"], TextSyndicationContentKind.Html);
            syndicationItem.PublishDate = item.Created;
    
            return syndicationItem;
        }
  
        return null;
    }
}

}

Configure an RSS feed item to use the custom type

enter image description here

enter image description here

Please refer here : https://www.sitecorespark.com/blog/2020/6/creating-and-customizing-an-rss-feed-in-sitecore

Upvotes: 0

Georgi
Georgi

Reputation: 11

All you need is to do two things:

  1. Override method RenderItem from Sitecore.Syndication.PublicFeed

Here is a very simple example, but in the overriding method you could insert your custom XML namespaces and whatever you want:

using Sitecore.Data.Items;
using Sitecore.Syndication;
using System.ServiceModel.Syndication;
using System.Xml.Linq;

namespace MyWebsite.Foundation.RssFeeds.Services
{
    public class CustomRssFeed : PublicFeed
    {
        protected override SyndicationItem RenderItem(Item item)
        {
            SyndicationItem syndicationItem = base.RenderItem(item);
            syndicationItem.ElementExtensions.Add(new XElement("addedNode", "addedContent"));

            return syndicationItem;
        }
    }
}
  1. Fill-in your custom public feed class in Sitecore. The place where to do this is in your RSS Feed item - it should have been created from template "/sitecore/templates/System/Feeds/RSS Feed". Enter the full names of your class and assembly in field "Type" (under section "Extensibility").

Example: "MyWebsite.Foundation.RssFeeds.Services.CustomRssFeed, MyWebsite.Foundation.RssFeeds" Screenshot

Here is a nice link for RSS feed customization

Upvotes: 1

Related Questions