Блоки скриптов с использованием 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>