1   Overview

 

The purpose of this article is to describe an approach in getting Sitecore Items using the XSL Extension.

 

2     Target Audience

 

The target audience for this example is a .NET developer and is doing Sitecore development.

 

3     Assumption

 

  1.  Sitecore is fully configured in the development machine.
  2. The /sitecore/content/home/Movies/ node exist and has items. The items should also have ‘Title’ field for our code example to run.  

 

4     Basic Idea

 

The idea is to retrieve Sitecore Items using the XSL Extension and return the Items to the calling XSLT. Unlike the usual way of retrieving a Sitecore Items by means of XPATH, it is more easy and convenient to use the XSL Extension. Using the XSL Extension, a developer can make additional condition or add more logic with the Items s/he wants to retrieve. In this document, an example is presented with the requirement to sort the Items in descending order before returning to the calling XSLT. 

 

5     Development Approach

 

The Environment:

The development environment/ technology used in this example are as follows:

  1. Sitecore 5.3
  2. VS 2008
  3. LINQ
  4. C#
  5. XSL, XSLT

 

The Extension:

 

  • From the Sitecore solution in the Visual Studio, add new class with the name of “MyExtensions.cs”. The code has initial code like below.

 

namespace MyNamespace
{
    public class MyExtensions
    {
        public MyExtensions()
        { }
    }
}

 

  • Add the namespaces System.Xml, System.Xml.XPath in the using section of the class.
  • Add a public function “GetLatestItems” with a return type of XmlNodeIterator. The XPathNodeIterator class provides an iterator over the set of nodes.

  Inside the “GetLatestItems”, add the following code:

public XPathNodeIterator GetLatestItems()
        {
            string node = "/sitecore/content/home/Movies/*";

            IOrderedEnumerable<Item> itemsRetrieved = null;

            itemsRetrieved = GetItems(node);
           
            Packet packet = new Packet();

            if (itemsRetrieved != null)
            {
                ExtractXML(ref packet, itemsRetrieved);
            }
            return packet.XmlDocument.CreateNavigator().Select("//sitecore");
        }

 

Our purpose here is to get the latest items under the /sitecore/content/home/Movies/ node.

 

The itemsRetrieved variable with IOrderedEnumerable of Item type will hold the items that we will retrieve and sorted. The actual retrieval and sorting of items is inside the “GetItems()” method.

 

The packet is responsible for building our XML documents.

 

The ExtractXML() method extracts the XML document or Item and aggregates into the packet variable.

 

And lastly, we create a XPathNavigator object by invoking the CreateNavigator() method of the XmlDocument inside the packet.

 

  • Implement the GetItems() method. Add the following code:

 

private IOrderedEnumerable<Item> GetItems(string node)
        {  
            Database db = Sitecore.Context.Database;
            Item[] nodeItems = db.SelectItems(node);

            if (nodeItems != null)
            {
                var sortedItems = from items in nodeItems
                                  where items.Versions.Count > 0
                                  orderby items.Fields["__created"].Value descending,
                                  items.Fields["Title"].Value ascending
                                  select items;

                return sortedItems;
            }
            return null;
        }

 

The “Sitecore.Context.Database” is the current database being used. We could also specifically use the master database like Factory.GetDatabase(“master”) if we want to.

 

The SelectItems() method of the Database retrieved all the items from the node that we specify. Items will be returned as Item array.

 

From the returned array of Item, we apply the logic to filter what we only want to return to the calling method.

The “where” clause in this example tell us to get only the item in which it has a version in the current language. This is very useful if you have multiple language but some items have no version for a specific language.

 

The “orderby” clause simply sorted the items based on the “__created” field, a field which is Sitecore defined, and by “Title” field.

 

  • Implement the ExtractXML() method. Add the following code:

 

private void ExtractXML(ref Packet packet, IOrderedEnumerable<Item> items)
        {
            if (packet != null && items != null)
            {
                XmlDocument doc;
                foreach (var item in items)
                {
                    doc = new XmlDocument();
                    doc.LoadXml(item.GetOuterXml(false));
                    packet.AddElement(doc.FirstChild);
                }
            }
        }

 

The ExtractXML method simply extracts the Item’s XML representation and added to the packet.

 

  • Compile the project.

 

The web.config:

  1. Inside the <xslExtensions> </xslExtensions> add the following code:

 

<extension mode=”on” type=”MyNamespace.MyExtensions”, MyAssembly” namespace=”www.mydomain.com/myext”

 

The “www.mydomain.com/myext” namespace must be unique. It is used to refer to the MyNamespace.MyExtensions class of the MyAssembly assembly in the XSLT.

 

Implementing the Extension:

  1. Create an XSLT. Add the code below in the namespace declaration above.

 

xmlns:myext="http://www.pluggedinonline.com/myext"

 

It's the prefix for our XSL Extension. It points to the namespace defined in the <xslExtensions> section in the web.config.

 

<xsl:template match="*" mode="main">        
        <ul>
            <xsl:variable name="dataItem" select='myext:GetLatestItems()'/>
            <xsl:for-each select="$dataItem/item">
                <li>
                    <xsl:value-of select="sc:fld('Title',.)"/>
                </li>
            </xsl:for-each>
        </ul>
    </xsl:template>

 

The dataItem will hold the values returned from myext:GetLatestItems(). The next line just loops for each the items returned and display the value of the ‘Title’ field.

 

6     Conclusion

 

While accessing Items directly from the XSL is useful, it is more efficient to use XSL Extension if you have complex logic to perform in retrieving Sitecore Items.

 

7     Reference

 

  1. Creating Sitecore XSL Extension Function

http://sdn5.sitecore.net/Articles/XSL/Using%20XSL%20Extension%20Objects/Creating%20Sitecore%20XSL%20Extension%20Function.aspx

Let say you have a list of items and you want to display them in a table-like format. What you would do is to loop over those items and render each item in a column. And again you have a requirements that:

there must only have two columns and the left column' color is different from the right; and

alternating rows must also have different color. 

 

Here is a sample code to accomplish that.

 

 <xsl:template match="*" mode="main">

        <xsl:variable name="dataItem" select='your list of items, let say 8'/>

        <table border='1' width='250px' cellspacing="5px"  >
            <xsl:apply-templates  mode='table' select='$dataItem/item[position() mod 2 = 1]'  />
        </table>

    </xsl:template>

    <xsl:template mode="table" match="item" >
        <xsl:variable name="itemSet" select=". | following-sibling::item[position() &lt; 2]"/>
        <xsl:apply-templates select="$itemSet[position() mod 2 = 1]" mode="row">
            <xsl:with-param name="row" select="position()"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="item" mode="row">
        <xsl:param name="row"/>
        <xsl:variable name="rowColor">
            <xsl:choose>
                <xsl:when test="($row mod 2)=0">
                    <xsl:value-of select="'background-color:maroon;'"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="'background-color:black;'"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>

        <tr style="{$rowColor}" height="50px">
            <xsl:apply-templates mode="col" select=". |following-sibling::item[position() &lt; 2]">
                <xsl:with-param name="row" select="$row"/>
            </xsl:apply-templates>
        </tr>
    </xsl:template>

    <xsl:template match="item" mode="col">
        <xsl:param name="row"/>
        <xsl:variable name="color">
            <xsl:choose>
                <xsl:when test="(position() mod 2)=0">
                    <xsl:value-of select="'background-color:yellow;'"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="'background-color:green;'"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>

        <td width="50%">
            <div  style="{$color}">
                row: <xsl:value-of select="$row" />
                <br/>
                col: <xsl:value-of select="position()"/>
            </div>
        </td>
    </xsl:template>

The code above will render the image below:

Here is an example on how to sort a date field in xsl in Sitecore.

<xsl:template match="*" mode="main">

<ul>

<xsl:for-each select="item">

<!-- year --><

xsl:sort select="substring(sc:fld('__created',.),1,4)" order="descending"/>

<!-- month --><

xsl:sort select="substring(sc:fld('__created',.),5,2)" order="descending"/>

<!-- day -->

<xsl:sort select="substring(sc:fld('__created',.),7,2)" order="descending"/>

<li>

<sc:link ><

sc:text field="title" />

<sc:dot /></

sc:link>

</li>

</xsl:for-each>

</ul>

</xsl:template>