代码如下:

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
*/
}
}
我的机器配置如下:赛扬900,512M内存。编译采用VS C# Express 2005
开始时候的测试循环次数是10次,结果发现太小,分辨不开,结果采用1000次循环,结果出现了很多性能异常情况,分析结果是循环次数太多导致内存耗用太大,影响评测,结果用循环100次得到这个结果,基本满意。
从结果中我们可以看到,XPathDocument支持的xslt转换速度始终最快,无论xslt中是否包含xpath引用。其次是XmlDocument支持的转换,最后才是XmlDataDocument。
而在优化方面,预先装入XML而运行时装入xslt要比预先装入XSLT而运行时装入xml的测试速度要慢差不多一个级别,说明系统装入xslt的耗费远比装入xml的耗费要大得多。大家以后一定要注意,不要经常去 new XslTransform() ,一定要预先装载好xslt。
另外需要注意的是,使用XmlDataDocument支持的转换,即使在全部cache的情况下,也和其他两种方法全部没有cache的情况一样速度。而且和最快方案的速度差距竟然有6倍之多!!!
最后,尝试了好几下去上传图片,结果都没有成功。怎么回事啊?图片17k,300x400点阵的gif。谁帮我一下?
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了