Monday, September 14, 2009

Simple xslt example

In this post i'll show how 2 make a simple xsl transform.
In addition i'll show how to use this xsl elements:

1. XsltArgumentList - pass arguments to the xslt
2. Encoding - declare the outgoing xml encoding
3. xsl:value-of - take the value(inner text) of node
4. xsl:copy-of - copy the inner xml of node
5. xsl:for-each - loop through same nodes
6. xsl:sort - sort nodes by specified node

and in the end of the post there is a c# thread safety class to make xsl transforms

so, this is the origin xml file(Person.xml):

<hPerson>
<Header>

<FirstName>Yosi</FirstName>
<LastName>Havia</LastName>
<Age>30</Age>
<Education>BA</Education>
</Header>
<hChildren>
<hChild>
<hName>Carol</hName>
<hAge>13</hAge>
</hChild>
<hChild>
<hName>Angela</hName>
<hAge>15</hAge>
</hChild>
<hChild>
<hName>Benjamin</hName>
<hAge>17</hAge>
</hChild>
</hChildren>
</hPerson>


and this is the xslt file(Person.xslt):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" omit-xml- declaration="yes"/>
<xsl:param name="Gender"></xsl:param>
<xsl:template match="/">
<Person>
<Gender>
<xsl:choose>
<xsl:when test="$Gender='1'">
Male
</xsl:when>
<xsl:otherwise>
Female
</xsl:otherwise>
</xsl:choose>
</Gender>
<xsl:copy-of select="/hPerson/Header"/>
<Data>
<Children>
<xsl:for-each select="/hPerson/hChildren/hChild">
<xsl:sort select="hName" />
<Child>
<FirstName>
<xsl:value-of select="hName"/>
</FirstName>
<Age>
<xsl:value-of select="hAge"/>
</Age>
</Child>
</xsl:for-each>
</Children>
</Data>
</Person>
</xsl:template>
</xsl:stylesheet>

the output xml look like this:

<?xml version="1.0" encoding="UTF-8"?>
<Person>
<Gender>
Male
</Gender>
<Header>
<FirstName>Yosi</FirstName>
<LastName>Havia</LastName>
<Age>30</Age>
<Education>BA</Education>
</Header>
<Data>
<Children>
<Child>
<FirstName>Angela</FirstName>
<Age>15</Age>
</Child>
<Child>
<FirstName>Benjamin</FirstName>
<Age>17</Age>
</Child>
<Child>
<FirstName>Carol</FirstName>
<Age>13</Age>
</Child>
</Children>
</Data>
</Person>

this is a thread safety c# class to make xsl transforms

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;

namespace XSLT
{
class XsltObj
{
protected static XslCompiledTransform _oXslTransform;
protected static object _oSyncXsl = new object();
public string FormatXmlWrapper(string sEncoding, XsltArgumentList
oXsltArgumentList,XmlDocument oOriginXmlDoc, string sXslPath)
{
string sRetVal = null;
if (_oXslTransform == null)
{
LoadXslWrapper(sXslPath, ref _oXslTransform, ref _oSyncXsl);
}
//@@@ make the transform
try
{
sRetVal = TransformData(sEncoding, _oXslTransform, oOriginXmlDoc,
oXsltArgumentList);
}
catch (Exception ex)
{
throw ex;
}
return sRetVal;
}
protected void LoadXslWrapper(string sXslPath,
ref XslCompiledTransform oXslTransform, ref object oSyncXsl)
{
lock (oSyncXsl)
{
if (oXslTransform == null)
{
XslCompiledTransform oTempXslTransform =
new XslCompiledTransform();
//@@@ get the xml path from configuration
LoadXsl(sXslPath, ref oTempXslTransform);
oXslTransform = oTempXslTransform;
}
}
}
protected void LoadXsl(string sXslPath, ref XslCompiledTransform
oXslCompiledTransform)
{
//@@@ load the xsl document(only once)
XmlDocument xslDocument = new XmlDocument();
XmlUrlResolver urlResolver = new XmlUrlResolver();
urlResolver.Credentials = System.Net.CredentialCache.DefaultCredentials;
xslDocument.XmlResolver = urlResolver;
try
{
//@@@ load the xsl document
xslDocument.Load(sXslPath);
XPathNavigator oXPathNavigator = xslDocument.CreateNavigator();
oXslCompiledTransform.Load(oXPathNavigator,
XsltSettings.TrustedXslt, urlResolver);
}
catch (Exception ex)
{
throw ex;
}
}
protected string TransformData(string sEncoding, XslCompiledTransform
oXslTransform, XmlDocument xmlDocument, XsltArgumentList argumentList)
{
StringBuilder sb = new StringBuilder();
string sDeclaration;
//@@@ decide the xml declaration up to the Encoding
if (string.IsNullOrEmpty(sEncoding))
sDeclaration = "version=\"1.0\"";
else
sDeclaration = "version=\"1.0\" encoding=\"" + sEncoding + "\"";
//@@@ make the xsl Transform
using (XmlWriter output = XmlWriter.Create(sb))
{
output.WriteProcessingInstruction("xml", sDeclaration);
XPathNavigator oXPathNavigator = xmlDocument.CreateNavigator();
oXslTransform.Transform(oXPathNavigator, argumentList, output);
return sb.ToString();
}
}
}
}

to activate this object use this code:

static void Main(string[] args)
{
XsltObj oXsltObj = new XsltObj();
XsltArgumentList oXsltArgumentList = GetXsltArguments();
XmlDocument oXmlDocument = new XmlDocument();
string sXmlPath = @"Person.xml";
string sXslPath = @"Person.xslt";
oXmlDocument.Load(sXmlPath);
string sXml = oXsltObj.FormatXmlWrapper("UTF-8", oXsltArgumentList,
oXmlDocument, sXslPath);
}
protected static XsltArgumentList GetXsltArguments()
{
//@@@ create the arguments for the xsl
XsltArgumentList list = new XsltArgumentList();
list.AddParam("Gender", string.Empty, "1");
return list;
}