一概述
XSLT可以用于将XML格式的数据转换为其它格式,在数据和展示分开以及数据相互转换中可以得到广泛的应用,比较典型的是以前的动网论坛模板系统以及动易的标签系统。掌握好XSLT可以灵活的处理XML,同时运用在Web应用程序中也非常的方便,不过缺点是使用者需要掌握大量的XPath、XSLT、XML等相关知识。
在XSLT中,可以直接使用脚本语言如Javascript输出到Html中,进行相关的客户端操作,由于一些限制,XSLT提供的函数可能不能达到一些复杂的数据处理效果,这个时候就需要使用扩展脚本块的功能,这样就可以使用C#等强类型的语言进行相关的数据处理工作。
在.Net中可以进行XSLT转换功能的类是XslCompiledTransform ,具体参考msdn.microsoft.com/zh-tw/library/system.xml.xsl.xslcompiledtransform(zh-cn).aspx
关于本文叙述的内容可以参考http://msdn.microsoft.com/zh-tw/library/wxaw5z5e(zh-cn).aspx
关于Xslt以及XPath可在网上参考相关文档。
二实现msxsl:script的功能
下面举一个例子实现该功能
1,新建一Web应用程序项目
2,在项目中添加一个Xml文件News.xml,内容如下:
- <?xml version="1.0" encoding="utf-8" ?>
- <AllNews>
- <News Author="Raymond">
- <Title>测试新闻标题1test test</Title>
- <Content>这里是新闻的内容</Content>
- </News>
- <News Author="Jack">
- <Title>测试新闻标题2 test test test</Title>
- <Content>这里是新闻的内容</Content>
- </News>
- <News Author="Tom">
- <Title>测试新闻标题3 test test test test</Title>
- <Content>这里是新闻的内容</Content>
- </News>
- </AllNews>
3,新建一个Xslt文件News.xslt,用于将Xml转换为Html内容如下:
- <?xml version="1.0" encoding="utf-8"?>
- <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="html" indent="yes"/>
- <xsl:template match="/">
- <xsl:call-template name="style"/>
- <xsl:call-template name="showNews">
- <xsl:with-param name="news" select="AllNews/News"/>
- </xsl:call-template>
- </xsl:template>
- <xsl:template name="style">
- <style>
- .title{font-size:14px;font-weight:bold;color:White;background-color:#000000;}
- div.newsBlock{border:1px dashed #000000;padding:5px;margin-bottom:10px;background-color:Gray;}
- div.content{text-indent:2em;}
- </style>
- </xsl:template>
- <!--展示新闻-->
- <xsl:template name="showNews">
- <xsl:param name="news"/>
- <xsl:for-each select="$news">
- <div class="newsBlock">
- <div class="title">
- <xsl:value-of select="Title"/>
- </div>
- <div class="content">
- <xsl:value-of select="Content"/>(<xsl:value-of select="@Author"/>)
- </div>
- </div>
- </xsl:for-each>
- </xsl:template>
- </xsl:stylesheet>
4,在Web项目的Default.aspx.cs中添加解析Xml的代码并且输出:
添加代码如下:
- protected void Page_Load(object sender, EventArgs e)
- {
- this.ShowNews();
- }
- /// <summary>
- /// 转换Xml并且显示新闻
- /// </summary>
- private void ShowNews()
- {
- //实例化
- XslCompiledTransform transform = new XslCompiledTransform();
- //加载样式表
- transform.Load(Server.MapPath("News.xslt"));
- //转换并且输出
- transform.Transform(Server.MapPath("News.xml"), null, Response.OutputStream);
- }
浏览Default.aspx 我们可以看到效果如下:
这样数据就正确的显示出来了
5,添加脚本块
我们试想一种情况,Xml中的一些数据可能通过xslt的函数无法处理那么这个时候我们需要借助于其他语言进行处理,这个时候我们可以考虑使用扩展脚本块来实现。
这里举一个例子,我们将新闻的标题仅显示前边7个字符,我们通过扩展的C#函数来处理(当然直接通过xslt的substring可以直接处理,这里仅举例而已,在一些情况下xslt自带函数无法实现很多跟业务逻辑层、数据层等相关的操作的情况下可以使用此方法)。
5.1,新建一个类库项目AssemblyTest
添加类XsltTest
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace AssemblyTest
- {
- public class XsltTest
- {
- /// <summary>
- /// 返回缩减的标题
- /// </summary>
- /// <param name="title"></param>
- /// <returns></returns>
- public static string GetTitle(string title)
- {
- return title.Substring(0, 7);
- }
- }
- }
5.2在Web应用程序中添加对AssemblyTest类库项目的引用
5.3修改News.xslt内容为
- <?xml version="1.0" encoding="utf-8"?>
- <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"
- xmlns:pl="http://www.polarlight.net/xslt/example">
- <msxsl:script language="C#" implements-prefix="pl">
- <msxsl:assembly name="AssemblyTest"/>
- <msxsl:using namespace="AssemblyTest"/>
- <![CDATA[
- public static string GetTitle(string title)
- {
- return AssemblyTest.XsltTest.GetTitle(title);
- }
- ]]>
- </msxsl:script>
- <xsl:output method="html" indent="yes"/>
- <xsl:template match="/">
- <xsl:call-template name="style"/>
- <xsl:call-template name="showNews">
- <xsl:with-param name="news" select="AllNews/News"/>
- </xsl:call-template>
- </xsl:template>
- <xsl:template name="style">
- <style>
- .title{font-size:14px;font-weight:bold;color:White;background-color:#000000;}
- div.newsBlock{border:1px dashed #000000;padding:5px;margin-bottom:10px;background-color:Gray;}
- div.content{text-indent:2em;}
- </style>
- </xsl:template>
- <!--展示新闻-->
- <xsl:template name="showNews">
- <xsl:param name="news"/>
- <xsl:for-each select="$news">
- <div class="newsBlock">
- <div class="title">
- <xsl:value-of select="pl:GetTitle(Title)"/>
- </div>
- <div class="content">
- <xsl:value-of select="Content"/>(<xsl:value-of select="@Author"/>)
- </div>
- </div>
- </xsl:for-each>
- </xsl:template>
- </xsl:stylesheet>
请大家留意上面红色部分,并思考为什么要这样做
5.4再次打开Default.aspx,这个时候我们可以看到也没抛出以下异常:
禁止执行脚本。使用 XsltSettings.EnableScript 属性可以启用。 D:\Users\Administrator\Documents\Visual Studio 2008\Projects\ConsoleTest\WebApplicationTest\News.xslt(40,11) 处出错
这个时候我们还需要对Default.aspx.cs的内容,允许执行脚本
5.5修改Default.aspx.cs的ShowNews方法为:
- /// <summary>
- /// 转换Xml并且显示新闻
- /// </summary>
- private void ShowNews()
- {
- //实例化
- XslCompiledTransform transform = new XslCompiledTransform();
- //加载样式表 new XsltSettings(false, true)第二个参数允许执行脚本
- transform.Load(Server.MapPath("News.xslt"), new XsltSettings(false, true), null);
- //转换并且输出
- transform.Transform(Server.MapPath("News.xml"), null, Response.OutputStream);
- }
5.6重新生成项目,这个时候浏览Default.aspx就可以看到如下效果:
三延伸扩展
通过以上例子我们可以看到配合msxsl:script我们可以用强类型的语言如C#来处理xml数据。动易的标签系统如pe:GetNode等其实就是通过这种方法来实现的,并没有任何复杂的技术。
1,使用.Net的控件通过xslt转换xml为html
除了上述方法以外,我们可以使用.Net自带的控件来显示Xml数据,如XmlDataSource
在Default.aspx中添加相关控件
- <asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="~/News.xml" XPath="/AllNews/News"></asp:XmlDataSource>
- <br />
- <style>
- .title
- {
- font-size: 14px;
- font-weight: bold;
- color: White;
- background-color: #000000;
- }
- div.newsBlock
- {
- border: 1px dashed #000000;
- padding: 5px;
- margin-bottom: 10px;
- background-color: Gray;
- }
- div.content
- {
- text-indent: 2em;
- }
- </style>
- <asp:Repeater ID="Repeater1" runat="server" DataSourceID="XmlDataSource1">
- <HeaderTemplate>
- 通过控件直接显示:
- </HeaderTemplate>
- <ItemTemplate>
- <div class="newsBlock">
- <div class="title">
- <%#XPath("Title") %>
- </div>
- <div class="content">
- <%#XPath("Content") %>
- (<%#XPath("@Author") %>)
- </div>
- </div>
- </ItemTemplate>
- </asp:Repeater>
再次打开Default.aspx页面我们可以看到同样的效果:
2,通过xslt转换Xml为Html只是一种转换方式,还可以转换为其它格式的Xml或者文本,这在一个xml用于不同程序不同xml架构中尤其有用。
3,利用xslt+xml可以实现一些扩展性很强、灵活性强的应用,缺点就是需要掌握Xpath和Xml相关知识。
4,允许执行脚本块会带来一定的安全风险比如被黑客篡改脚本块C#的内容,执行一些非法操作,所以在使用的时候应小心谨慎。
5,Xslt中的数据类型与CLR对应关系:
为函数提供的参数和返回值可以是任意类型。 因为 W3C XPath 类型是公共语言运行库 (CLR) 类型的子集,所以,对不属于 XPath 类型的类型进行类型转换。 下表显示相应的 W3C 类型和等效的 CLR 类型。
W3C 类型 | CLR 类型 |
---|---|
String | String |
Boolean | Boolean |
Number | Double |
Result Tree Fragment | XPathNavigator |
Node Set | XPathNodeIterator |
CLR 数字类型转换为 Double。 DateTime 类型转换为 String。IXPathNavigable 类型转换为 XPathNavigator。 XPathNavigator 转换为 XPathNodeIterator。
所有其他类型均将引发错误。