Редагувати

Поділитися через


Script Blocks Using msxsl:script

Note

Script blocks are supported only in .NET Framework. They are not supported on .NET Core or .NET 5 or later.

The XslCompiledTransform class supports embedded scripts using the msxsl:script element. When the style sheet is loaded, any defined functions are compiled to common intermediate language (CIL) by the Code Document Object Model (CodeDOM) and are executed during run time. The assembly generated from the embedded script block is separate than the assembly generated for the style sheet.

Enable XSLT Script

Support for embedded scripts is an optional XSLT setting on the XslCompiledTransform class. Script support is disabled by default. To enable script support, create an XsltSettings object with the EnableScript property set to true and pass the object to the Load method.

Note

XSLT scripting should be enabled only if you require script support and you are working in a fully trusted environment.

msxsl:script Element Definition

The msxsl:script element is a Microsoft extension to the XSLT 1.0 recommendation and has the following definition:

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

The msxsl prefix is bound to the urn:schemas-microsoft-com:xslt namespace URI. The style sheet must include the xmlns:msxsl=urn:schemas-microsoft-com:xslt namespace declaration.

The language attribute is optional. Its value is the code language of the embedded code block. The language is mapped to the appropriate CodeDOM compiler using the CodeDomProvider.CreateProvider method. The XslCompiledTransform class can support any Microsoft .NET language, assuming the appropriate provider is installed on the machine and is registered in the system.codedom section of the machine.config file. If a language attribute is not specified, the language defaults to JScript. The language name is not case-sensitive so 'JavaScript' and 'javascript' are equivalent.

The implements-prefix attribute is mandatory. This attribute is used to declare a namespace and associate it with the script block. The value of this attribute is the prefix that represents the namespace. This prefix can be defined somewhere in a style sheet.

Note

When using the msxsl:script element, we strongly recommend that the script, regardless of language, be placed inside a CDATA section. Because the script can contain operators, identifiers, or delimiters for a given language, if it is not contained within a CDATA section, it has the potential of being misinterpreted as XML. The following XML shows a template of the CDATA section where code can be placed.

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

Script Functions

Functions can be declared within the msxsl:script element. When a function is declared, it is contained in a script block. Style sheets can contain multiple script blocks, each operating independent of the other. That means that if you are executing inside a script block, you cannot call a function that you defined in another script block unless it is declared to have the same namespace and the same scripting language. Because each script block can be in its own language, and the block is parsed according to the grammar rules of that language parser we recommend that you use the correct syntax for the language in use. For example, if you are in a Microsoft C# script block, use the C# comment syntax.

The supplied arguments and return values to the function can be of any type. Because the W3C XPath types are a subset of the common language runtime (CLR) types, type conversion takes place on types that are not considered to be an XPath type. The following table shows the corresponding W3C types and the equivalent CLR type.

W3C type CLR type
String String
Boolean Boolean
Number Double
Result Tree Fragment XPathNavigator
Node Set XPathNodeIterator

CLR numeric types are converted to Double. The DateTime type is converted to String. IXPathNavigable types are converted to XPathNavigator. XPathNavigator[] is converted to XPathNodeIterator.

All other types throw an error.

Importing Namespaces and Assemblies

The XslCompiledTransform class predefines a set of assemblies and namespaces that are supported by default by the msxsl:script element. However, you can use classes and members belonging to a namespace that is not on the predefined list by importing the assembly and namespace in msxsl:script block.

Assemblies

The following two assemblies are referenced by default:

  • System.dll

  • System.Xml.dll

  • Microsoft.VisualBasic.dll (when the script language is VB)

You can import the additional assemblies using the msxsl:assembly element. This includes the assembly when the style sheet is compiled. The msxsl:assembly element has the following definition:

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

The name attribute contains the name of the assembly and the href attribute contains the path to the assembly. The assembly name can be a full name, such as "System.Data, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", or a short name, such as "System.Web".

Namespaces

The following namespaces are included by default:

  • System

  • System.Collection

  • System.Text

  • System.Text.RegularExpressions

  • System.Xml

  • System.Xml.Xsl

  • System.Xml.XPath

  • Microsoft.VisualBasic (when the script language is VB)

You can add support for additional namespaces using the namespace attribute. The attribute value is the name of the namespace.

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

Example

The following example uses an embedded script to calculate the circumference of a circle given its radius.

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>

Output

<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>

See also