Блоки скриптов с использованием msxsl:script

Примечание.

Блоки скриптов поддерживаются только в .NET Framework. Они не поддерживаются в .NET Core или .NET 5 или более поздней версии.

Класс XslCompiledTransform поддерживает внедренные скрипты с помощью элемента msxsl:script. При загрузке таблицы стилей все определенные функции компилируются на общий промежуточный язык (CIL) моделью объектов кода (CodeDOM) и выполняются во время выполнения. Сборка, создаваемая из блока внедренного скрипта, располагается отдельно от сборки, создаваемой для таблицы стилей.

Включение скрипта XSLT

Поддержка внедренных скриптов является необязательным параметром XSLT в классе XslCompiledTransform. По умолчанию поддержка скриптов отключена. Чтобы включить поддержку скриптов, создайте объект XsltSettings со значением свойства EnableScript, равным true, и передайте его методу Load.

Примечание.

Скрипты XSLT следует включать только при необходимости в поддержке скриптов и при работе в полностью доверенной среде.

Определение элемента msxsl:script

Элемент msxsl:script введен корпорацией Майкрософт в качестве расширения рекомендации XSLT 1.0 и имеет следующее определение:

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

Префикс msxsl привязан к URI-коду пространства имен urn:schemas-microsoft-com:xslt. Таблица стилей должна содержать декларацию пространства имен xmlns:msxsl=urn:schemas-microsoft-com:xslt.

Атрибут language является необязательным. Его значением является язык кода внедренного блока. Язык сопоставляется с необходимым компилятором CodeDOM с помощью метода CodeDomProvider.CreateProvider. Класс XslCompiledTransform может поддерживать любой язык платформы Microsoft .NET при условии, что на компьютере установлен соответствующий поставщик, зарегистрированный в разделе system.codedom файла machine.config. Если атрибут 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>

См. также