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.

  • Jens Mikkelsen

    About the author:

    Jens Mikkelsen

    Jens Mikkelsen is currently employed by Pentia A/S a Sitecore consulting firm. Here he holds a position in Pentias core team as Core Technology Specialist. The position covers a lot of different roles from architect, to lead developer, to consultant. The core team is responsible for supporting all departments in Pentia including the project, sales and moduledepartment. The tasks include everything from code reviews and architecture to development methology to technical presales.

     

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

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

Great little article for new Sitecore developers.
Posted: Tuesday, July 21, 2009 5:38 PM

Leave a reply

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