使用 msxsl:script 的脚本块

注释

脚本块仅在 .NET Framework 中受支持。 .NET Core 或 .NET 5 或更高版本 不支持 它们。

XslCompiledTransform 类支持使用 msxsl:script 元素来嵌入脚本。 加载样式表时,代码文档对象模型(CodeDOM)会将任何定义的函数编译为公共中间语言(CIL),并在运行时执行。 从嵌入脚本块生成的程序集与为样式表生成的程序集分开。

启用 XSLT 脚本

对嵌入式脚本的支持是 XslCompiledTransform 类的一个可选 XSLT 设置。 默认情况下禁用脚本支持。 若要启用脚本支持,请创建一个XsltSettings对象,并将EnableScript属性设置为true,然后将该对象传递给Load方法。

注释

仅当需要脚本支持并且正在使用完全受信任的环境中时,才应启用 XSLT 脚本。

msxsl:script 元素定义

msxsl:script 元素是 XSLT 1.0 建议的Microsoft扩展,具有以下定义:

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

前缀 msxsl 绑定到 urn:schemas-microsoft-com:xslt 命名空间 URI。 样式表必须包含 xmlns:msxsl=urn:schemas-microsoft-com:xslt 命名空间声明。

language 属性是可选项。 其值是嵌入代码块的代码语言。 此语言通过 CodeDomProvider.CreateProvider 方法映射到相应的 CodeDOM 编译器。 该 XslCompiledTransform 类可以支持任何Microsoft .NET 语言,假设相应的提供程序安装在计算机上,并在 machine.config 文件的 system.codedom 节中注册。 language如果未指定属性,则语言默认为 JScript。 语言名称不区分大小写,因此“JavaScript”和“javascript”是等效的。

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

注释

在使用 msxsl:script 元素时,强烈建议将脚本放置在 CDATA 节中,无论其语言为何。 由于脚本可以包含给定语言的运算符、标识符或分隔符,如果 CDATA 节中不包含该运算符、标识符或分隔符,因此它有可能被误解为 XML。 以下 XML 显示了 CDATA 节的模板,可在其中放置代码。

<msxsl:script implements-prefix='your-prefix' language='CSharp'>
<![CDATA[
// Code block.
]]>
</msxsl:script>

脚本函数

可以在 msxsl:script 元素中声明函数。 声明函数时,该函数包含在脚本块中。 样式表可以包含多个脚本块,每个脚本块独立于另一个脚本块。 这意味着,如果在脚本块内执行,则不能调用在另一个脚本块中定义的函数,除非声明该函数具有相同的命名空间和相同的脚本语言。 由于每个脚本块可以采用自己的语言,并且该块根据该语言分析器的语法规则进行分析,因此我们建议你对正在使用的语言使用正确的语法。 例如,如果在 Microsoft C# 脚本块中,请使用 C# 注释语法。

提供给函数的参数和返回值可以是任何类型的。 由于 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.

所有其他类型都引发错误。

导入命名空间和程序集

XslCompiledTransform 类预定义了一组由 msxsl:script 元素默认支持的程序集和命名空间。 然而,您可以通过在 msxsl:script 块中导入程序集和命名空间,使用不属于预定义列表的命名空间的类和成员。

程序集

默认情况下引用下列两个程序集:

  • System.dll

  • System.Xml.dll

  • Microsoft.VisualBasic.dll(脚本语言为 VB 时)

可以使用 msxsl:assembly 元素导入其他程序集。 包括在编译样式表时的程序集。 该 msxsl:assembly 元素具有以下定义:

<msxsl:script>
  <msxsl:assembly name="system.assemblyName" />
  <msxsl:assembly href="path-name" />
    <![CDATA[
    // User code
    ]]>
</msxsl:script>

name 属性包含程序集的名称,属性 href 包含程序集的路径。 程序集名称可以是全名,例如“System.Data、Version=2.0.3600.0、Culture=neutral、PublicKeyToken=b77a5c561934e089”或短名称,如“System.Web”。

命名空间

默认情况下包括以下命名空间:

  • 系统

  • System.Collection

  • System.Text

  • System.Text.RegularExpressions(系统.文本.正则表达式)

  • System.Xml

  • System.Xml.Xsl

  • System.Xml.XPath

  • Microsoft.VisualBasic (脚本语言为 VB 时)

可以使用该 namespace 属性添加对其他命名空间的支持。 属性值是命名空间的名称。

<msxsl:script>
  <msxsl:using namespace="system.namespaceName" />
    <![CDATA[
    // User code
    ]]>
</msxsl:script>

示例:

以下示例使用嵌入式脚本来计算给定圆半径的周长。

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() {

    // Compile the style sheet.
    XsltSettings xslt_settings = new XsltSettings();
    xslt_settings.EnableScript = true;
    XslCompiledTransform xslt = new XslCompiledTransform();
    xslt.Load(stylesheet, xslt_settings, new XmlUrlResolver());

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

    // Create an XmlWriter.
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.OmitXmlDeclaration = true;
    settings.Indent = true;
    XmlWriter writer = XmlWriter.Create("output.xml", settings);

    // Execute the transformation.
    xslt.Transform(doc, writer);
    writer.Close();
  }
}
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()

        ' Compile the style sheet.
        Dim xslt_settings As XsltSettings = New XsltSettings()
        xslt_settings.EnableScript = true
        Dim xslt As XslCompiledTransform = New XslCompiledTransform()
        xslt.Load(stylesheet, xslt_settings, New XmlUrlResolver())

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

        ' Create an XmlWriter.
        Dim settings As XmlWriterSettings = New XmlWriterSettings()
        settings.OmitXmlDeclaration = true
        settings.Indent = true
        Dim writer As XmlWriter = XmlWriter.Create("output.xml", settings)

        ' Execute the transformation.
        xslt.Transform(doc, writer)
        writer.Close()
    End Sub
End Class

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>

另请参阅