在.Net framework中有个XslCompiledTransform类,它只能处理XSLT1.0的样式表,微软目前官方也不准备提供对2.0的支持。然而这并不是说,我们就不能在.Net中使用XSLT2.0的新特性,通过第三方提供的类库,可以实现同样的目的。
XSLT2.0比起1.0更强大,提供了更方便的方法,以下是2.0中的几个主要改进:
- 支持正则表达式
- 提供更多的函数处理时间,像获取当前时间,格式化时间
- 用户定义函数,xsl:function
- 字符串比较
tokenize()
和matches()方法
- for … in … return
- next-match
- as 属性 ,<xsl:variable name="i" as="xs:integer" select="@size"/> 或 <xsl:function name="str:reverse" as="xs:string">
查看所有的方法和新的特性都去网站W3C,w3schools上列出了所有函数。
目前知名的第三方控件,包括
Saxon , 这个可以用于Java和.Net,而且它提供了开源和商业两个不同的版本。在这个例子中, 我们用Saxon .NET API来说明如何使用XSLT2.0。
XML源文档:
<?xml version="1.0" encoding="utf-8"?> <cities> <city name="Milano" country="Italia" pop="1307495" /> <city name="Paris" country="France" pop="2220140" /> <city name="Bordeaux" country="France" pop="719489" /> <city name="München" country="Deutschland" pop="1260391" /> <city name="Lyon" country="France" pop="474946" /> <city name="Venezia" country="Italia" pop="270801" /> <city name="Delft" country="Holland" pop="94512" /> <city name="Rotterdam" country="Holland" pop="607460" /> </cities> |
预期输出:
XSLT 文件:
<?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes" encoding="iso-8859-1" /> <xsl:template match="/"> <html> <head> <title>Cities</title> </head> <body> Generated at <xsl:value-of select="format-dateTime(current-dateTime(), '[D].[M].[Y] [H]:[m]:[s]' )" /> <br /> <table style="border : 1px solid #000;"> <thead> <tr> <th>Position</th> <th>Country</th> <th>City List</th> <th>Population</th> </tr> </thead> <tbody> <xsl:for-each-group select="cities/city" group-by="@country"> <xsl:sort select="sum(current-group()/@pop)" data-type="number" order="descending" /> <tr> <td> <xsl:value-of select="position()" /> </td> <td> <xsl:value-of select="@country" /> </td> <td> <xsl:value-of select="current-group()/@name" separator=", " /> </td> <td> <xsl:value-of select="sum(current-group()/@pop)" /> </td> </tr> </xsl:for-each-group> </tbody> </table> </body> </html> </xsl:template> </xsl:stylesheet> |
这个XSLT包含单个模板,它的规则就是将XML内容转化成HTML格式。
在XML中, 包含一组城市列表,在输出的HTML中,会对城市分组,然后根据人口数的多少排序。在上面的XSLT中,我们用xsl:for-each-group指令对城市分组,在1.0中我们也可以实现分组功能,只是实现起来更复杂,2.0直接提供了内置的支持。另外一个有用的函数就是current-dateTime()和format-dateTime()方法,对于时间相关的操作,这两个方法非常有用。
.Net 代码:
namespace Saxon { internal class Program { private static void Main() { const string xmlFile = @"..\..\cities.xml"; const string xsltFile = @"..\..\cities.xslt"; const string outFile = @"..\..\cities_grouped.html"; try { using (XmlReader xml = XmlReader.Create(xmlFile)) using (XmlReader xslt = XmlReader.Create(xsltFile)) { // Create a Processor instance var processor = new Processor(); // Load the source document XdmNode input = processor.NewDocumentBuilder(). Build(xml); // Create a transformer for the stylesheet XsltTransformer transformer = processor.NewXsltCompiler(). Compile(xslt).Load(); // Set the root node of the source document to be the initial context node transformer.InitialContextNode = input; // Create a serializer var serializer = new Serializer(); serializer.SetOutputStream(new FileStream(outFile, FileMode.Create, FileAccess.Write)); // Transform the source XML transformer.Run(serializer); Console.WriteLine("Output written to " + outFile + Environment.NewLine); } } catch (Exception e) { ConsoleColor currentConsoleColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("oops : " + e.Message); Console.ForegroundColor = currentConsoleColor; } Console.Write("Press any key to exit ..."); Console.ReadKey(); } } } |
其它第三方控件:
XQSharp, AltovaXML 这些类库都可以.Net环境中使用。
源代码:
http://files.cnblogs.com/zhaojin/Saxon.zip