Generate Sitemap.xml with Sitecore

This blog will give a small demo about how to create customized solution in Sitecore. We will be creating a sitemap.xml in this blog.

In sitecore, request are served through pipelines and 1st pipeline is “httpRequestBegin“.

This pipeline is having many processors in it. If any new request comes, there are steps which will create the complete request. (for more detail about different pipeline, Click Here )

Here, the request will traverse through the specified processors to create the result of the request.

Follow the steps to generate sitemap.xml:

Step 1: Create Sitecore content tree structure for the site. This structure could be different with Sitemap.

sitemapcontenttree

Step 2: Create Processor for HttpRequestBegin pipeline,

File: UrlSet.cs (Model)

using System.Collections.Generic;
using System.Xml.Serialization;

namespace Sitemap.Models
{
    ///

    /// Class to generate urlset for sitemap
    /// 

    [XmlRoot("urlset")]
    public class Urlset
    {
        ///

        /// Constructor to initialize Url Object
        /// 

        public Urlset() { Url = new List(); }

        ///

        /// Urls collection
        /// 

        [XmlElement("url")]
        public List Url { get; set; }

    }

    ///

    /// Class to generate url with its parameters for sitemap
    /// 

    public class Url
    {
        ///

        /// Location Parameter
        /// 

        [XmlElement("loc")]
        public string Loc { get; set; }

        ///

        /// Last modified on
        /// 

        [XmlElement("lastmod")]
        public string Lastmod { get; set; }

        //Add required properties here like changefreq, priority
    }
}

Filename: Sitemap.cs

#region Namespaces
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Serialization;
using Sitecore;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Links;
using Sitecore.Pipelines.HttpRequest;
using Sitemap.Models;
#endregion

#region Main Code
namespace Sitemap.Pipelines.HTTPRequestBegin
{
    public class Sitemap : HttpRequestProcessor
    {
        public override void Process(HttpRequestArgs args)
        {
            //This check will verify if the physical path of the request exists or not.
            if (!System.IO.File.Exists(args.HttpContext.Request.PhysicalPath) &&
                !System.IO.Directory.Exists(args.HttpContext.Request.PhysicalPath))
            {
                Assert.ArgumentNotNull(args, "args");
                //Check if the request is of sitemap.xml then only allow the request to serve sitemap.xml
                if (args.Url == null || !args.Url.FilePath.ToLower().EndsWith("sitemap.xml")) return;
                try
                {
                    // Homepage of the Website.
                    // Start path will give homepage including Multisite.
                    var homepage = Context.Database.GetItem(args.StartPath);
                    var ser = new XmlSerializer(typeof(Urlset));

                    var urlSet = new Urlset();

                    //Create node of Homepage in Sitemap.
                    var tmpurlset = new List();
                    var config = AppendLanguage();

                    if (!ExcludeItemFromSitemap(homepage))
                    {
                        tmpurlset.Add(new Url
                        {
                            Loc = GetAbsoluteLink(LinkManager.GetItemUrl(homepage, new UrlOptions() { LanguageEmbedding = (config == 2 ? LanguageEmbedding.Always : (config == 1 ? LanguageEmbedding.AsNeeded : LanguageEmbedding.Never)) })),
                            Lastmod = homepage.Statistics.Updated.ToString("yyyy-MM-dd hh:mm:ss")
                        });
                    }

                    // Get all decendants of Homepage to create full Sitemap.
                    var childrens = homepage.Axes.GetDescendants();
                    //Remove the items whose templateid is in exclude list
                    var finalcollection = childrens.Where(x => !ExcludeItemFromSitemap(x)).ToList();

                    tmpurlset.AddRange(finalcollection.Select(childItem => new Url
                    {
                        Loc = GetAbsoluteLink(LinkManager.GetItemUrl(childItem, new UrlOptions() { LanguageEmbedding = (config == 2 ? LanguageEmbedding.Always : (config == 1 ? LanguageEmbedding.AsNeeded : LanguageEmbedding.Never)) })),
                        Lastmod = childItem.Statistics.Updated.ToString("yyyy-MM-dd hh:mm:ss")
                    }));

                    // Populate created collection to right object
                    urlSet.Url = tmpurlset;

                    //Write XML Response for Sitemap.
                    var response = HttpContext.Current.Response;
                    response.AddHeader("Content-Type", "text/xml");
                    ser.Serialize(response.OutputStream, urlSet);
                    HttpContext.Current.Response.End();
                    //Response Ends Here
                }
                catch (Exception ex)
                {
                    Log.Error("Error - Sitemap.xml.", ex, this);
                }
            }
        }

        ///

        /// Crete Absolute url as per the site
        /// 

        ///
        ///
        private static string GetAbsoluteLink(string relativeUrl)
        {
            return HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Host + relativeUrl;
        }

        ///

        /// Append language or not in URL to return language specific sitemap.xml
        /// 

        ///
        private static int AppendLanguage()
        {
            return string.IsNullOrEmpty(Sitecore.Configuration.Settings.GetSetting("LanguageEmbedForSitemap")) ? 0 : System.Convert.ToInt32((Sitecore.Configuration.Settings.GetSetting("LanguageEmbedForSitemap")));
        }

        ///

        /// This method will get a list of excluding template ids and will check if the passed item is in
        /// 

        ///
        ///
        private static bool ExcludeItemFromSitemap(Item objItem)
        {
            //Check if the item is having any version
            if (objItem.Versions.Count > 0)
            {
                var excludeItems = Sitecore.Configuration.Settings.GetSetting("ExcludeSitecoreItemsByTemplatesInSitemap");
                var collection = excludeItems.Split(',').ToList();
                return collection.Contains(objItem.TemplateID.ToString());
            }
            return true;
        }
    }
}
#endregion

Step 3: Create new config like “sitemap.config” at like “\Website\App_Config\Include\z_custom\”. Content will be as below.

 

2018-05-22 14_58_38-VShared.Sitemap

 

All done now, Here is the result:

sitemapresult3

So,

  • sitemap.xml will be generate on request and so actual file not required to be saved on the server or anywhere.
  • sitemap.xml will be generated from any page even if user is on any child page.
  • This supports in MVC and WebForm both.
  • This supports Multilingual as well.
  • To exclude any items based on Template ID, specify the template ID in “ExcludeSitecoreItemsByTemplatesInSitemap” node of sitemap.config
  • Specify “LanguageEmbedForSitemap” option as per requirement

Link of Sitecore marketplace module ready to use is here.

Also the code is available at Git link.

Cheers for now.

Advertisements

6 thoughts on “Generate Sitemap.xml with Sitecore

Add yours

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: