This site uses cookies to deliver our services. By using this site, you acknowledge that you have read and understand our Cookie and Privacy policy. Your use of Kontext website is subject to this policy. Allow Cookies and Dismiss

在.Net中使用msxsl:script脚本块扩展XSLT的具体实践与应用

352 views 0 comments last modified about 9 years ago Raymond Tang

一概述

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 数字类型转换为 DoubleDateTime 类型转换为 StringIXPathNavigable 类型转换为 XPathNavigatorXPathNavigator[] 转换为 XPathNodeIterator

所有其他类型均将引发错误。

Related pages

Issue - Unable to get property 'apply' of undefined or null reference occurred in Angular 4.*, VS2017 15.3, ASP.NET Core 2.0

7039 views   10 comments last modified about 2 years ago

Issue Context After installed Visual Studio 2017 15.3 preview and .net core 2.0 preview SDK, I upgraded one of my existing asp.net core project to 2.0. The project was created using ‘dotnet new angular’ SPA template.&nbsp; I also upgraded all the client app packages to the latest. For exa...

View detail

[Link] Build SPA on ASP.NET Core with JavaScript Services

475 views   0 comments last modified about 2 years ago

Great introduction about JavaScriptServices ( JavaScriptServices GitHub repository ): Microsoft.AspNetCore.SpaTemplates plugs into dotnet new , providing project templates for Angular 2, Aurelia, Knockout...

View detail

input submit input text css的写法

122 views   0 comments last modified about 10 years ago

本文介绍如何修改input控件submit以及text不同类型的样式。

View detail

JavaScript版本的杨辉三角

289 views   0 comments last modified about 9 years ago

前几天帮一个学弟写的,JavaScript版本的杨辉三角,其实和其他C、Java等等版本的都差不多。代码如下:

View detail

在网页中通过userAgent获取手机获取手机操作系统类型

1410 views   0 comments last modified about 7 years ago

本文介绍如果在JavaScript中根据手机浏览器提供的信息userAgent判断手机操作系统的类型,并执行相应的操作。

View detail

My First Silverlight Applet: Silverlight + xml 图片轮换展示效果

282 views   2 comments last modified about 9 years ago

这是自己的第一个Silverlight程序,没有专门的学习过Silverlight,界面效果不是很好(很丑 ),全是凭自己的感觉以及对xml和winform的了解转移到Silverlight上来的,效果参考了网上经常可以看到的Flash+Xml 图片或者广告轮番展示效果,不过我这个功能暂时不是很强大,仅仅是实现了最初的功能,以后再慢慢修改,效果参看 www.polarlight.net/D...

View detail

Add comment

Please login first to add comments.  Log in New user?  Register

Comments (0)

No comments yet.