
Using directives#region Using directives

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

#endregion

namespace testXsltTransform


{
class Program

{
static string xml0, xslt0, prefix;


definition#region definition
const string const_xml0 =
"<?xml version=/"1.0/" encoding=/"UTF-8/"?>" +
"<Table>" +
" <Row>" +
" <Caption>Hello</Caption>" +
" <Text>this is a hello</Text>" +
" </Row>" +
" <Row>" +
" <Caption>Hello2</Caption>" +
" <Text>this is a hello2</Text>" +
" </Row>" +
" <Row>" +
" <Caption>Hello3</Caption>" +
" <Text>this is a hello3</Text>" +
" </Row>" +
"</Table>";
const string const_xslt0 =
"<?xml version=/"1.0/" encoding=/"UTF-8/"?>" +
"<xsl:stylesheet version=/"1.0/" " +
" xmlns:xsl=/"http://www.w3.org/1999/XSL/Transform/">" +
" <xsl:output method=/"html/" version=/"1.0/" encoding=/"UTF-8/" indent=/"yes/"/>" +
"" +
" <xsl:template match=/"//">" +
" <html>" +
" <head>" +
" <title>hello</title>" +
" </head>" +
" <body>" +
" <xsl:apply-templates />" +
" </body>" +
" </html>" +
" </xsl:template>" +
" " +
" <xsl:template match=/"Table/">" +
" <table border=/"1/">" +
" <body>" +
" <xsl:apply-templates />" +
" </body>" +
" </table>" +
" </xsl:template>" +
" " +
" <xsl:template match=/"Row/">" +
" <tr>" +
" <xsl:apply-templates />" +
" </tr>" +
" </xsl:template>" +
" " +
" <xsl:template match=/"Caption/">" +
" <td><xsl:value-of select=/"./"/></td>" +
" </xsl:template>" +
"" +
" <xsl:template match=/"Text/">" +
" <td><xsl:value-of select=/"./"/></td>" +
" </xsl:template>" +
"</xsl:stylesheet>";
const string const_xslt1 =
"<?xml version=/"1.0/" encoding=/"UTF-8/"?>" +
"<xsl:stylesheet version=/"1.0/" xmlns:xsl=/"http://www.w3.org/1999/XSL/Transform/">" +
" <xsl:output method=/"html/" version=/"1.0/" encoding=/"UTF-8/" indent=/"yes/"/>" +
"" +
" <xsl:template match=/"//">" +
" <html>" +
" <head>" +
" <title>hello</title>" +
" </head>" +
" <body>" +
" <xsl:apply-templates />" +
" </body>" +
" </html>" +
" </xsl:template>" +
" " +
" <xsl:template match=/"Table/">" +
" <table border=/"1/">" +
" <body>" +
" <xsl:apply-templates select=/"//Row/" />" +
" </body>" +
" </table>" +
" </xsl:template>" +
" " +
" <xsl:template match=/"Row/">" +
" <tr>" +
" <td><xsl:value-of select=/"Caption/"/></td>" +
" <td><xsl:value-of select=/"Text/"/></td>" +
" </tr>" +
" </xsl:template>" +
" " +
"</xsl:stylesheet>";
#endregion

public Program(string _prefix, string xml, string xslt)

{
prefix = _prefix;
xml0 = xml;
xslt0 = xslt;
}

public interface IXmlLoader

{
XPathNavigator GetXml();
}

public interface ITransformLoader

{
XslTransform GetTransform();
}


XPath Loader#region XPath Loader
public class XPathXmlLoader : IXmlLoader

{
public XPathNavigator GetXml()

{
XPathDocument doc = new XPathDocument();
doc.LoadXml(xml0);
return doc.CreateNavigator();
}
}

public class XPathXsltLoader : ITransformLoader

{
public XslTransform GetTransform()

{
XPathDocument xslt = new XPathDocument();
xslt.LoadXml(xslt0);
XslTransform trans = new XslTransform();
trans.Load(xslt as IXPathNavigable);
return trans;
}
}
#endregion


XmlDocument Loader#region XmlDocument Loader
public class XDocXmlLoader : IXmlLoader

{
public XPathNavigator GetXml()

{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml0);
return doc.CreateNavigator();
}
}

public class XDocXsltLoader : ITransformLoader

{
public XslTransform GetTransform()

{
XmlDocument xslt = new XmlDocument();
xslt.LoadXml(xslt0);
XslTransform trans = new XslTransform();
trans.Load(xslt as IXPathNavigable);
return trans;
}
}
#endregion


XmlDataDocument Loader#region XmlDataDocument Loader
public class XmlDataDocumentXmlLoader : IXmlLoader

{
public XPathNavigator GetXml()

{
XmlDataDocument doc = new XmlDataDocument();
doc.LoadXml(xml0);
return doc.CreateNavigator();
}
}

public class XmlDataDocumentXsltLoader : ITransformLoader

{
public XslTransform GetTransform()

{
XmlDataDocument xslt = new XmlDataDocument();
xslt.LoadXml(xslt0);
XslTransform trans = new XslTransform();
trans.Load(xslt as IXPathNavigable);
return trans;
}
}
#endregion


cache#region cache
public class XmlLoaderCache : IXmlLoader

{
XPathNavigator nav;
public XmlLoaderCache(IXmlLoader loader)

{
nav = loader.GetXml();
}

public XPathNavigator GetXml()

{
return nav;
}
}

public class XsltLoaderCache : ITransformLoader

{
XslTransform trans;
public XsltLoaderCache(ITransformLoader t)

{
trans = t.GetTransform();
}

public XslTransform GetTransform()

{
return trans;
}
}
#endregion

void trans(IXmlLoader xml, ITransformLoader trans)

{
//using (MemoryStream output = new MemoryStream())
using(NullStream output = new NullStream())

{
trans.GetTransform().Transform(xml.GetXml(), null, output);
output.Flush();
//Console.WriteLine(Encoding.Default.GetString(output.ToArray()));
}
}

public class NullStream : System.IO.Stream

{

public override bool CanRead
{get
{ return false; }}


public override bool CanSeek
{get
{ return false; }}


public override bool CanWrite
{get
{ return true; }}


public override void Flush()
{}

public override long Length
{get
{ throw new global::System.NotImplementedException(); }}

public override long Position

{

get
{throw new global::System.NotImplementedException();}

set
{throw new global::System.NotImplementedException();}
}


public override int Read(byte[] buffer, int offset, int count)
{throw new NotImplementedException();}


public override long Seek(long offset, SeekOrigin origin)
{throw new NotImplementedException();}


public override void SetLength(long value)
{throw new NotImplementedException();}


public override void Write(byte[] buffer, int offset, int count)
{}
}

public class Tri

{
public string descr;
public IXmlLoader xml;
public ITransformLoader trans;
public Tri(string _des, IXmlLoader _xml, ITransformLoader _trans)

{
descr = _des; xml = _xml; trans = _trans;
}
}


testcode#region testcode
void doTest()

{
Tri[] tris = new Tri[]

{
new Tri(prefix + "doc: no cache", new Program.XDocXmlLoader(), new Program.XDocXsltLoader() ),
new Tri(prefix + "xpath: no cache", new Program.XPathXmlLoader(), new Program.XPathXsltLoader() ),
new Tri(prefix + "datadoc: no cache", new Program.XmlDataDocumentXmlLoader(), new Program.XmlDataDocumentXsltLoader()),

new Tri(prefix + "doc: doc cache", new Program.XmlLoaderCache(new Program.XDocXmlLoader()), (new Program.XDocXsltLoader()) ),
new Tri(prefix + "xpath: doc cache", new Program.XmlLoaderCache(new Program.XPathXmlLoader()), (new Program.XPathXsltLoader()) ),
new Tri(prefix + "datadoc: doc cache", new Program.XmlLoaderCache(new Program.XmlDataDocumentXmlLoader()), (new Program.XmlDataDocumentXsltLoader())),

new Tri(prefix + "doc: xslt cache", (new Program.XDocXmlLoader()), new Program.XsltLoaderCache(new Program.XDocXsltLoader()) ),
new Tri(prefix + "xpath: xslt cache", (new Program.XPathXmlLoader()), new Program.XsltLoaderCache(new Program.XPathXsltLoader()) ),
new Tri(prefix + "datadoc: xslt cache", (new Program.XmlDataDocumentXmlLoader()), new Program.XsltLoaderCache(new Program.XmlDataDocumentXsltLoader())),

new Tri(prefix + "doc: all cache", new Program.XmlLoaderCache(new Program.XDocXmlLoader()), new Program.XsltLoaderCache(new Program.XDocXsltLoader()) ),
new Tri(prefix + "xpath: all cache", new Program.XmlLoaderCache(new Program.XPathXmlLoader()), new Program.XsltLoaderCache(new Program.XPathXsltLoader()) ),
new Tri(prefix + "datadoc: all cache", new Program.XmlLoaderCache(new Program.XmlDataDocumentXmlLoader()), new Program.XsltLoaderCache(new Program.XmlDataDocumentXsltLoader()))
};

object[,] result = new object[1 + 5, tris.Length]; // col:round, row:testcase

Tri t;
for (int j = 0; j < result.GetLength(0); ++j) // foreach round

{
Console.WriteLine("round " + j.ToString());
for(int c = 0; c < tris.Length; ++c)

{
t = tris[c];
if (j == 0)
result[j, c] = t.descr;
else

{
DateTime start = DateTime.Now;
for (int i = 0; i < 100; ++i)
this.trans(t.xml, t.trans);
DateTime end = DateTime.Now;

int span = ((TimeSpan)(end - start)).Milliseconds;
result[j, c] = span;
}
}
}

// print result
Console.WriteLine("result:");
for (int row = 0; row < result.GetLength(1); ++row)

{
for (int col = 0; col < result.GetLength(0); ++col)

{
Console.Write(result[col, row]);
Console.Write('/t');
}
Console.WriteLine();
}
}
#endregion

static void Main(string[] args)

{

Program prog = new Program("xslt1 ", const_xml0, const_xslt0);
prog.doTest();

prog = new Program("xslt2 ", const_xml0, const_xslt1);
prog.doTest();
}


/**//*
Console Display:
round 0
round 1
round 2
round 3
round 4
round 5
result:
xslt1 doc: no cache 220 210 240 220 210
xslt1 xpath: no cache 210 190 180 180 190
xslt1 datadoc: no cache 370 360 360 350 360
xslt1 doc: doc cache 180 190 190 200 190
xslt1 xpath: doc cache 150 150 150 160 150
xslt1 datadoc: doc cache 620 640 640 620 610
xslt1 doc: xslt cache 90 90 70 90 80
xslt1 xpath: xslt cache 80 70 80 70 80
xslt1 datadoc: xslt cache 180 190 180 180 180
xslt1 doc: all cache 50 50 50 60 50
xslt1 xpath: all cache 40 50 40 40 40
xslt1 datadoc: all cache 430 440 420 450 410
round 0
round 1
round 2
round 3
round 4
round 5
result:
xslt2 doc: no cache 220 200 220 230 220
xslt2 xpath: no cache 160 250 170 170 160
xslt2 datadoc: no cache 360 390 360 350 370
xslt2 doc: doc cache 170 180 180 170 170
xslt2 xpath: doc cache 150 140 140 150 160
xslt2 datadoc: doc cache 630 650 711 701 761
xslt2 doc: xslt cache 80 80 80 80 80
xslt2 xpath: xslt cache 140 70 80 70 70
xslt2 datadoc: xslt cache 200 180 170 180 180
xslt2 doc: all cache 80 50 50 40 50
xslt2 xpath: all cache 50 40 40 40 30
xslt2 datadoc: all cache 550 430 440 450 450
*/
}
}