Thursday, April 16, 2009

Sitecore.NVelocity

Apparently I was working with Sitecore and its mail template. Sitecore suggest using nVelocity for template rendering. I notices that they have their own version of nVelocity called Sitecore.NVelocity. The base code is essentially the same and the code for rendering the template is slightly different as follows ( as in original Velocity)

In the constructor

Velocity.Init();


For rendering call 


Velocity.Evaluate(context, generated, "nVelocityLog", reader);

nVelocity to render templates

nVelocity is a .Net-based template engine. It permits anyone to use the simple yet powerful template language to reference objects defined in .Net code. I use this template engine for rendering the mail templates in my application. This is a wonderful framework, with a defined syntax to render field values inside the template. For those who do not know, project is a port of the Jakarta Velocity to Microsoft .Net (written in C#). This is a discontinued project, but the Castle project fork  enhanced it to support their monorail implementation. There are different versions available, I used one from Castle project website which has a lot of bug fixes and features incorporated than the original.

Below is the sample code to illustrate nVelocity to render mail template.

using System;
using System.Collections.Generic;
using System.IO;
using Commons.Collections;
using NVelocity;
using NVelocity.App;
using System.Collections;

namespace NVelocitySample
{
class Program
{
static VelocityEngine velocity;
static void Main(string[] args)
{
InitializeVelocity();

string output = GenerateOutput();
Console.WriteLine(output);
}

private static void InitializeVelocity()
{
ExtendedProperties properties = new ExtendedProperties();

velocity = new VelocityEngine(properties);
}


private static string GenerateOutput()
{
Message mail = new Message();


mail.From = "sender@company.com";
mail.To = "recipient@company.com";
mail.Subject = "This a mail render example";
mail.Body = "This is the body where replace a dictionary to show the versatility of nVelocity";


Dictionary<string, string> coll = new Dictionary<string, string>();
coll["key"] = "Hi,";



string stringData = "From: $mail.From \n";
stringData += "To: $mail.To \n\n";
stringData += "Subject: $mail.Subject \n\n";
stringData += "$coll.get_Item('key') $mail.Body";


Hashtable hashTable = new Hashtable();
hashTable.Add("mail", mail);
hashTable.Add("coll", coll);

VelocityContext context = new VelocityContext(hashTable);

StringWriter generated = new StringWriter();
StringReader reader = new StringReader(stringData);
velocity.Evaluate(context, generated, "nVelocityLog", reader);
return generated.GetStringBuilder().ToString();


}


class Message
{
private string from;
private string to;
private string subject;
private string body;

public string From
{
get { return from; }
set { from = value; }
}

public string To
{
get { return to; }
set { to = value; }
}

public string Subject
{
get { return subject; }
set { subject = value; }
}

public string Body
{
get { return body; }
set { body = value; }
}
}

class Coll
{
Dictionary<string, string> fields = new Dictionary<string, string>();

public Dictionary<string, string> Fields
{
get { return fields; }
set { fields = value; }
}
}
}
}




Thursday, April 9, 2009

Calling C# function in XSL

In my current project, someone was looking for calling a C# function in XSL transformation. The following example calls a C# function declared in an external assembly for XSL transformation. DollerEuroConverter class is defined in the assembly CurrencyConverter.dll. The GetEuroValue function is just a sample implementation to show how the data from xsl can be modified using C# function. I tested it using a XML Notepad, I got the following output.

clip_image002

CurrencyConverter class

using System;
namespace CurrencyConverter
{
//our custom class
public class DollerEuroConverter
{
//function that gets called from XSLT
public string GetEuroValue(string xslDollar)
{
return (float.Parse(xslDollar) / 0.749962502).ToString("##.##");
}

}
}


CD.xml (Sample from w3schools)




<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title>Greatest Hits</title>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
<cd>
<title>Still got the blues</title>
<artist>Gary Moore</artist>
<country>UK</country>
<company>Virgin records</company>
<price>10.20</price>
<year>1990</year>
</cd>
</catalog>


CD.xsl




<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:MyClass="CurrencyConverter.DollerEuroConverter">


<msxsl:script language="C#" implements-prefix="MyClass">
<msxsl:assembly href=".\bin\Debug\CurrencyConverter.dll" />
<msxsl:using namespace="CurrencyConverter"/>

<![CDATA[

public string GetPrice(string data)

{
CurrencyConverter.DollerEuroConverter conveter = new CurrencyConverter.DollerEuroConverter();
string days = conveter.GetEuroValue(data);
return days;

}

]]>

</msxsl:script>

<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
<th>Price in Euro</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="artist"/>
</td>
<td>
<xsl:value-of select="MyClass:GetPrice(price)"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>