Level: 200
 

Getting started with XSL extensions - part 2

XSL image

This is the 2nd part of the series “Getting started with XSL extensions”. In this part you will learn to use parameters and get some tips on what to avoid, when using XSL extensions.

Written by: Jens Mikkelsen
Fri, Jun 5 2009

Using parameters:

It is pretty simple to parse parameters from your XSLT to your XSL extension. However you need to be careful with the types. There are no compile time errors, when parsing the wrong types as parameters or the return type for that matter. Instead you will get a runtime error in your XSLT.
You can pass a simple string to your XSL extension by adding a parameter to your extension method:

 

namespace LearnSitecore.Examples.XSL

{

  public class MyXSLExtension

  {

    public string StringParameter(string s)

    {

      return "!!!" + s + "!!!";

    }

  }

}

 

This can be called like this:

 

< xsl:value-of select = "ls:StringParameter('teststring')"/>

This will return “!!!teststring!!!”. You can also use other types such as integer. XSL doesn’t have the type system of C#, but the type is parsed in correctly anyway. Take a look at the following method:

 

namespace LearnSitecore.Examples.XSL

{

  public class MyXSLExtension

  {

    public int Add(int a, int b)

    {

      return a+b;

    }

  }

  }

This can be called with string values like this:

 

< xsl:value-of select = "ls:Add('1','41')"/>

This will correctly return 42 even though it is strings, which are parsed in. However if you parse in a string that cannot be converted to an integer, it will throw a runtime exception. Therefore you need to be careful when parsing in values from Sitecore fields, which don’t use validation to ensure the type. Luckily Sitecore provides an integer field in Sitecore 6. Use this whenever you need this type.

 

One thing you often want to parse in is a Sitecore item. But when you parse an item in to you extension, it won’t be converted to an Item but an XPathNodeIterator. In the same matter you can’t return a Sitecore item. So you need a helper method, which converts items between an XPathNodeIterator and a Sitecore Item.

 

Imagine the hypothetical situation where you want a method, which returns the second child of an item. You don’t want to iterate over all the children in your XSLT, so you create an extension. You need to pass in the root as a parameter and return the second child and create the method like this:

 

public XPathNodeIterator GetSecondChild(XPathNodeIterator root)

{

  Item rootItem = ItemFromXPathNodeIterator(root);

  return XPathNodeIteratorFromItem(rootItem.Children[1]);

}

 

Here the methods ItemFromXPathNodeIterator and XPathNodeIteratorFromItem do the work of converting the type. They look like this:¨

 

private Item ItemFromXPathNodeIterator(XPathNodeIterator root)

{

  if (!root.MoveNext())

    return null  

 

  //get id from current node

  string itemID = root.Current.GetAttribute("id", string.Empty);

  //get sc item

  return Sitecore.Context.Database.Items[itemID];

}

 

The method gets the item id from the XML and then looks it up in the current context database.

 

private XPathNodeIterator XPathNodeIteratorFromItem(Item item)

{

  if (item == null)

    return null;

  // Use the Sitecore Factory to generate a ItemNavigator and select the root

  Sitecore.Configuration.Factory.CreateItemNavigator(item).Select(".");

}

The method uses Sitecore’s API to get a XPathNodeIterator from an item.


The above code works fine and you’re doing fine. But suddenly your boss comes complaining. Some sides return a nasty XSL error. You realize that you haven’t validated your input. What if the root node doesn’t have two children? You will then get an index out of bound exception. Now XSLT’s doesn’t understand a null reference so you can’t return null. Instead you need to return an empty XPathNodeIterator like this:

 

public XPathNodeIterator GetSecondChild(XPathNodeIterator root)

{

  Item rootItem = ItemFromXPathNodeIterator(root);

  if (rootItem == null)

    return EmptyXPathNodeIterator();  

 

  if(rootItem.Children.Count < 2)

    return EmptyXPathNodeIterator();

  return XPathNodeIteratorFromItem(rootItem.Children[1]);

}

Where the EmptyXPathNodeIterator() looks like this:

 

private XPathNodeIterator EmptyXPathNodeIterator()

{

  XmlDocument doc = new XmlDocument();

  emptyNavigator = doc.CreateNavigator();

  return emptyNavigator.Select("*");

}

 

Now your method should be robust.

 

Well that’s it. You have now learned to create XSL extensions and use parameters… So congratulations! :)

 

Please rate this article


1 rates / 5 avg.

  • About the author:

    Jens Mikkelsen

    Jens Mikkelsen is a partner at Inmento Solutions a Sitecore consulting firm. He works as a Sitecore specialist and consulting helping clients architect and build quality Sitecore solutions using the newest modules and tools. 

    Further he has been deeply envolved in various complex solutions and has built up a strong knowledge of Sitecore architecture and best practices. He has especially focused on and is specialized in debugging and analyzing Sitecore solutions.

     

    Jens is very interested in the technical mechanisms in the new marketing products such as Sitecore DMS and Sitecore ECM.

    My Sitecore Freelance CV

3 responses to "Getting started with XSL extensions - part 2"

Great little article for new Sitecore developers.
Posted: Tuesday, July 21, 2009 5:38 PM
Thanks this article helped me too in my recent projects....
Thanks Again
Posted: Saturday, November 12, 2011 7:17 PM
I think the last statement in the XPathNodeIteratorFromItem method should do a return.

And thanks for your articles.
Posted: Friday, February 15, 2013 10:57 AM

Leave a reply


Notify me of follow-up comments via email.
 
 
#nbsp;