使用 <msxsl:script> 编写 XSLT 样式表脚本

XslTransform 类使用 script 元素支持嵌入的脚本。

注意注意

XslTransform 类在 .NET Framework 2.0 版 中已过期。可以使用 XslCompiledTransform 类执行可扩展样式表语言转换 (XSLT) 转换。有关更多信息,请参见使用 XslCompiledTransform 类从 XslTransform 类迁移

XslTransform 类使用 script 元素支持嵌入的脚本。 加载样式表时,任何已定义的函数都会通过包装在类定义中来编译为 Microsoft 中间语言 (MSIL),因此不会有任何性能损失。

<msxsl:script> 元素定义如下:

<msxsl:script language = "language-name" implements-prefix = "prefix of user namespace"> </msxsl:script>

其中 msxsl 是绑定到命名空间 urn:schemas-microsoft-com:xslt 的前缀。

language 属性不是强制属性,但如果指定该属性,其值必须是下列值之一:C#、VB、JScript、JavaScript、VisualBasic 或 CSharp。 如果未指定,则默认语言为 JScript。 language-name 不区分大小写,所以“JavaScript”和“javascript”等效。

implements-prefix 属性是必选项。 此属性用于声明命名空间并将其与脚本块关联。 此属性的值是表示命名空间的前缀。 此命名空间可以在样式表中的某一位置定义。

因为 msxsl:script 元素属于命名空间 urn:schemas-microsoft-com:xslt,因此样式表必须包含命名空间声明 xmlns:msxsl=urn:schemas-microsoft-com:xslt。

如果脚本的调用方没有 UnmanagedCode 访问权限,则样式表中的脚本将永不编译并且对 Load 的调用将失败。

如果调用方有 UnmanagedCode 权限,则脚本将编译,但允许的操作取决于加载时提供的证据。

如果使用一个接受 XmlReaderXPathNavigatorLoad 方法加载样式表,则需要使用接受 Evidence 实参作为其形参的 Load 重载。 为提供证据,调用方必须有为脚本程序集提供 Evidence 的 ControlEvidence 权限。 如果调用方没有此权限,则可以将 Evidence 参数设置为 null。 这会导致 Load 函数在发现脚本时失败。 ControlEvidence 权限是一种权力很大的权限,只应授予高度可信任的代码。

若要从您的程序集中得到证据,请使用 this.GetType().Assembly.Evidence。 若要从统一资源标识符 (URI) 得到证据,请使用 Evidence e = XmlSecureResolver.CreateEvidenceForUrl(stylesheetURI)。

如果使用接受 XmlResolver 但没有 Evidence 的 Load 方法,则程序集的安全区域默认为“完全信任”。 有关更多信息,请参见 SecurityZone命名权限集

函数可以在 msxsl:script 元素内声明。 下表显示了默认情况下支持的命名空间。 可以在列出的命名空间的外部使用类。 然而,这些类必须是完全限定的。

默认命名空间

说明

System

系统类。

System.Collection

集合类。

System.Text

文本类。

System.Text.RegularExpressions

正则表达式类。

System.Xml

核心 XML 类。

System.Xml.Xsl

XSLT 类。

System.Xml.XPath

XML 路径语言 (XPath) 类。

Microsoft.VisualBasic

用于 Microsoft Visual Basic 脚本的类。

声明函数时,该函数包含在脚本块中。 样式表可以包含多个脚本块,每个脚本块彼此独立运行。 也就是说,如果在脚本块的内部执行,则无法调用在其他脚本块中定义的函数,除非该脚本块声明为具有同一命名空间和同一脚本语言。 由于每个脚本块都可以使用自己的语言,因此脚本块的分析将遵照语言分析器的语法规则进行,必须使用适合所使用语言的语法。 例如,如果使用的是 C# 脚本块,则在该块中使用 XML 注释节点 <!-- an XML comment --> 是错误的。

由脚本函数定义的所提供的参数以及返回值必须是万维网联合会 (W3C) XPath 或 XSLT 类型之一。 下表显示了相应的 W3C 类型、等效的 .NET Framework 类(类型),以及 W3C 类型是 XPath 类型还是 XSLT 类型。

类型

等效的 .NET Framework 类(类型)

XPath 类型还是 XSLT 类型

String

System.String

XPath

Boolean

System.Boolean

XPath

Number

System.Double

XPath

结果树片断

System.Xml.XPath.XPathNavigator

XSLT

节点集

System.Xml.XPath.XPathNodeIterator

XPath

如果脚本函数使用下列数值类型之一:Int16、UInt16、Int32、UInt32、Int64、UInt64、Single 或 Decimal,则会将其强制转换为 Double,映射为 W3C XPath 类型的数字。 所有其他类型都通过调用 ToString 方法强制转换为字符串。

如果脚本函数使用上述类型以外的类型,或者如果函数在样式表加载到 XslTransform 对象中时不进行编译,则会引发异常。

当使用 msxsl:script 元素时,强烈建议无论使用何种语言,都应将脚本放置在 CDATA 节内。 例如,下面的 XML 显示放置代码的 CDATA 节的模板。

<msxsl:script implements-prefix='yourprefix' language='CSharp'>
    <![CDATA[
    ... your code here ...
    ]]>
</msxsl:script>

强烈建议将所有脚本内容都放置在 CDATA 节内,因为给定语言的运算符、标识符或分隔符有可能被错误地解释为 XML。 下面的示例显示如何在脚本中使用逻辑 AND 运算符。

<msxsl:script implements-prefix='yourprefix' language='CSharp>
    public string book(string abc, string xyz)
    {  if ((abc== abc)&&(abc== xyz)) return bar+xyz;
        else return null;
    }
</msxsl:script>

由于“&”符没有转义,因此将引发异常。 将文档作为 XML 加载,并且不对 msxsl:script 元素标记之间的文本应用任何特殊处理。

示例

已知圆的半径,下面的示例使用嵌入脚本计算圆的周长。

Imports System
Imports System.IO
Imports System.Xml
Imports System.Xml.XPath
Imports System.Xml.Xsl

Public Class Sample

   Private Const filename As String = "number.xml"
   Private Const stylesheet As String = "calc.xsl"

   Public Shared Sub Main()

    'Create the XslTransform and load the style sheet.
    Dim xslt As XslTransform = New XslTransform
    xslt.Load(stylesheet)

    'Load the XML data file.
    Dim doc As XPathDocument = New XPathDocument(filename)

    'Create an XmlTextWriter to output to the console.             
    Dim writer As XmlTextWriter = New XmlTextWriter(Console.Out)
    writer.Formatting = Formatting.Indented

    'Transform the file.
    xslt.Transform(doc, Nothing, writer, Nothing)
    writer.Close()
  End Sub 
End Class
using System;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;

public class Sample
{
   private const String filename = "number.xml";
   private const String stylesheet = "calc.xsl";

   public static void Main() {

    //Create the XslTransform and load the style sheet.
    XslTransform xslt = new XslTransform();
    xslt.Load(stylesheet);

    //Load the XML data file.
    XPathDocument doc = new XPathDocument(filename);

    //Create an XmlTextWriter to output to the console.             
    XmlTextWriter writer = new XmlTextWriter(Console.Out);
    writer.Formatting = Formatting.Indented;

    //Transform the file.
    xslt.Transform(doc, null, writer, null);
    writer.Close();
  } 
}

输入

number.xml

<?xml version='1.0'?>
<data>
  <circle>
    <radius>12</radius>
  </circle>
  <circle>
    <radius>37.5</radius>
  </circle>
</data>

calc.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:user="urn:my-scripts">

  <msxsl:script language="C#" implements-prefix="user">
     <![CDATA[
     public double circumference(double radius){
       double pi = 3.14;
       double circ = pi*radius*2;
       return circ;
     }
      ]]>
   </msxsl:script>

  <xsl:template match="data">  
  <circles>

  <xsl:for-each select="circle">
    <circle>
    <xsl:copy-of select="node()"/>
       <circumference>
          <xsl:value-of select="user:circumference(radius)"/> 
       </circumference>
    </circle>
  </xsl:for-each>
  </circles>
  </xsl:template>
</xsl:stylesheet>

输出

<circles xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:my-scripts">
  <circle>
    <radius>12</radius>
    <circumference>75.36</circumference>
  </circle>
  <circle>
    <radius>37.5</radius>
    <circumference>235.5</circumference>
  </circle>
</circles>  

请参见

概念

XslTransform 类实现 XSLT 处理器