Advanced XSLT
What’s XSLT? It’s a transformation known for making hard things easy and easy things hard. It can simplify the complex transformation logic that would be extremely tedious to implementation. But at the same time, the pure XSLT functional programming model makes it extremely difficult to achieve logic purpose.
How XSLT compare with C# on logic?
Out of question, it’s non-comparable. XSLT is designed for transformation, but less on logic. So, some times if we need to do transformation based on some logic, it makes the easy logic things difficult. But C# can take it easy….
Without .NET Framework, we usually reply on VBScript or JScript to expand the function of XSLT, writing our own custom XSLT function. But now, fortunately the .NET Framework bring new feature which we can expand the XSLT function in managed language, like C#, VB.NET even managed C++. And .NET Framework is integrant with XSLT perfectly. We can fetch the XSLT passed node as XPathNodeIterator object then operate it easily in our C# code.
The syntax of including managed code in XSLT is,
<msxsl:script language="c#" implements-prefix="csharp"></msxsl>
We can specify which language we adopt to use by setting attribute language. The attribute implements-prefix defines the prefix of this function calling. By the way, we should declare this prefix at the root node of XSLT xslt:stylesheet, like xmlns:csharp="http://lovinger2000.cnblogs.com". http://lovinger2000.cnblogs.com is only the custom namespace that we can give the name what we want.
Inner of the MSXSL declaration node, we can write the managed function in which language we like.
A simple sample,
<msxsl:script language="c#" implements-prefix="csharp">
<![CDATA[
private string Sum(int a, int b)
{
return a + b;
}
]]>
</msxsl>
We can call it just like a built-in XSLT function as following,
<xslt:variable name="numberA" select=”…” />
<xslt:variable name="numberB" select=”…” />
<xslt:value-of select="csharp:Sum(number($numberA), number($numberB))" />
Of course we also can get the result from our custom function like,
<xslt:variable name="result" select=”csharp: Sum(number($numberA), number($numberB))” />
So we can use the variable $result in the following XSLT code.
Pay attention that we should use <![CDATA[ and ]]> wrap the managed code. Otherwise, it raises error when there are some invalid xml characters like <, > and so on.
Let’s go deep into the other sample,
<msxsl:script language="c#" implements-prefix="cs">
<![CDATA[
private string Indent(string s, int maxLength)
{
if(maxLength<=0) return s;
System.Text.StringBuilder sbSentence = new System.Text.StringBuilder();
System.Collections.Specialized.StringCollection collection =
foreach (string str in collection)
{
if (sbSentence.Length + str.Length > maxLength - 4) break;
sbSentence.Append(str);
}
if (sbSentence.Length < s.Length)
{
return TrimPunctuation(sbSentence) + "...";
}
return sbSentence.ToString();
}
private string TrimPunctuation(System.Text.StringBuilder sb)
{
// Function Logic Here
}
private System.Collections.Specialized.StringCollection Split(string s)
{
// Function Logic Here
}
]]>
</msxsl:script>
This example shows how we can implement complex business logic in XSLT by embed C# code. The purpose of the code is to trim the string to maximum length. It trims by word, but not by character. So the result string displays all whole words.
Through this example, we can get that we can write separated XSLT just like a function library. And reference it by syntax <xslt:include href="XSLT PATH" />.
The last example is the advanced one, as following,
<msxsl:script language="C#" implements-prefix="user">
private string GetType(XPathNodeIterator nodeIterator)
{
return nodeIterator.GetType().Name;
}
private int Sum(XPathNodeIterator nodeIterator)
{
int d = 0;
while (nodeIterator.MoveNext())
d += Convert.ToInt32(nodeIterator.Current.Value);
return d;
}
</msxsl:script>
This sample shows we even can fetch the transforming xml node. From it, we can write more complex code for these nodes to achieve logic.

浙公网安备 33010602011771号