XslCompiledTransform 类使用 msxsl:script 元素支持嵌入的脚本。 在加载样式表式,任何已定义的函数将通过代码文档对象模型 (CodeDOM) 编译为 Microsoft 中间语言 (MSIL) 并在运行时执行。 从嵌入的脚本块生成的程序集比为样式表生成的程序集独立。
启用 XSLT 脚本
支持嵌入式脚本是 XslCompiledTransform 类上可选的 XSLT 设置。 默认情况下禁用脚本支持。 要启用脚本支持,创建一个 XsltSettings 对象,将 EnableScript 属性设置为 true,然后将该对象传递给 Load 方法。
![]() |
---|
只有要求脚本支持并且处于完全可信的环境下时,才应启用 XSLT 脚本。有关更多信息,请参见 System.Xml 安全注意事项。 |
msxsl:script 元素定义
msxsl:script 元素是 Microsoft 对 XSLT 1.0 建议的扩展,包括以下定义:
<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 |
|
Boolean |
|
Number |
|
Result Tree Fragment |
|
Node Set |
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
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>
示例
已知圆的半径,下面的示例使用嵌入脚本计算圆的周长。
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()
' 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
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();
}
}
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>