Tuesday 15 January 2008

Implementing the MVP Pattern in Sitecore XSLT Extension Methods

Here’s a way of implementing the MVP pattern when creating Sitecore XSLT extension methods. Ideally, you should already have some experience of creating extension methods and be familiar with MVP.

In the example I use, a “for-each” loop is used to display a list of makes of car.

First, create the view interface, defining the property or properties you want to display in the XSLT. As we are returning an array of values, the XPathNodeIterator return type is used:

public interface ICarsView
{

    XPathNodeIterator Cars { get; set; }

}


Create an interface defining the method that will get the data or information from store:

public interface ICar
{

    XPathNodeIterator GetListOfCars();

}


In your data access layer (DAL), implement the method that gets the data:

public XPathNodeIterator GetListOfCars()

{

    var cars = from c in GetMyData()

               orderby c.Make

               select c;

 

    XDocument xdoc = new XDocument();

    XElement xmlTree = new XElement("Cars");


    foreach( var car in cars )

    {

        xmlTree.Add(new XElement("Car",

            new XAttribute("Make", car.Make)));

    }


    xdoc.Add(xmlTree);


    return xdoc.CreateNavigator().Select("/Cars/Car");

}


Create the presenter class, which will store references to the view and DAL method interfaces, and define the method(s) that will set the value of the property or properties on the view:

    public class CarsPresenter

    {

        private readonly ICarsView _view;

        private readonly ICar _icar;

 

        public CarsPresenter( ICarsView view, ICar car )

        {

            _view = view;

            _icar = car;

        }

 

        public void SetCarsProperty()

        {

            _view.Cars = _icar.GetListOfCars();

        }

    }



Create the extension method that implements the view:

public class CarsView: ICarsView
{
    public XPathNodeIterator GetListOfCars()
    {
        CarsPresenter cp = new CarsPresenter(this, new CarsDal());
        cp.SetCarsProperty ();
        return Cars;
    }
 
    #region IAgreementsView Members
 
    public XPathNodeIterator Cars
    {
        get; set;
    }
 
    #endregion
}


In the web.config file, add an extension element to the xslExtensions element that references the concrete view. Use one such element for each namespace:

<extension mode="on" type="XsltViews.CarsView, XsltViews"
           namespace=" http://example.com/xsltviews/cars " />


In your XSLT file, declare the namespace prefix by adding it to the stylesheet element and including the prefix in the exclude-result-prefixes attribute:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:sc="http://www.sitecore.net/sc"
  xmlns:dot="http://www.sitecore.net/dot"
  xmlns:view="http://example.com/xsltviews/cars"
  exclude-result-prefixes="dot sc view">


Finally, you can now call the method from your XSLT:

<xsl:for-each select="view:GetListOfCars()">
  <xsl:value-of select="@Make"/>
</xsl:for-each>

No comments: