Blocos de script usando msxsl:script

Observação

Os blocos de script têm suporte apenas no .NET Framework. Não há suporte para eles no .NET Core ou no .NET 5 ou posterior.

A classe XslCompiledTransform oferece suporte a scripts inserido usando o elemento msxsl:script. Quando a folha de estilos é carregada, todas as funções definidas são compiladas para a Common Intermediate Language (CIL) pelo Modelo de Objetos do Documento de Código (CodeDOM) e executadas durante o runtime. O assembly gerado no bloco de script inserido é separado do assembly gerado para a folha de estilos.

Habilitar scripts XSLT

O suporte a scripts inseridos é uma configuração XSLT opcional na classe XslCompiledTransform. O suporte a script é desabilitado por padrão. Para habilitar o suporte a script, crie um objeto XsltSettings com a propriedade EnableScript definida para true e passe o objeto para o método Load.

Observação

O script XSLT deverá ser habilitado somente se você precisar de suporte a script e estiver trabalhando em um ambiente totalmente confiável.

Definição do elemento msxsl:script

O elemento msxsl:script é uma extensão da Microsoft para a recomendação XSLT 1.0 e tem a seguinte definição:

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

O prefixo msxsl é associado ao URI do namespace urn:schemas-microsoft-com:xslt. A folha de estilos deve incluir a declaração de namespace xmlns:msxsl=urn:schemas-microsoft-com:xslt.

O atributo language é opcional. Seu valor é a linguagem de código do bloco de código inserido. O idioma é mapeado para o compilador CodeDOM apropriado que usa o método CodeDomProvider.CreateProvider. A classe XslCompiledTransform pode oferecer suporte a qualquer linguagem do Microsoft .NET, supondo que o provedor apropriado esteja instalado no computador e registrado na seção de system.codedom do arquivo machine.config. Se o atributo language não for especificado, a linguagem assume JScript como padrão. O nome da linguagem não diferencia maiúsculas de minúsculas; portanto, 'JavaScript' e 'javascript' são equivalentes.

O atributo implements-prefix é obrigatório. Esse atributo é usado para declarar um namespace e associá-lo ao bloco de script. O valor desse atributo é o prefixo que representa o namespace. Este prefixo pode ser definido em qualquer lugar de uma folha de estilos.

Observação

Ao usar o elemento msxsl:script, é altamente recomendável que o script, independentemente da linguagem, seja colocado em uma seção CDATA. Como o script pode conter operadores, identificadores ou delimitadores para uma linguagem específica, caso ele não esteja em uma seção CDATA, ele podes ser interpretado incorretamente como XML. O XML a seguir mostra um modelo da seção CDATA em que o código pode ser inserido.

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

Funções de script

As funções podem ser declaradas no elemento msxsl:script. Quando uma função é declarada, ela está contida em um bloco de script. As folhas de estilos podem conter vários blocos de script, cada uma funcionando de maneira independente da outra. Isso significa que, se você estiver realizando a execução em um bloco de script, não poderá chamar uma função definida em outro bloco de script, a menos que tenha sido declarado que ela tem o mesmo namespace e a mesma linguagem de script. Como cada bloco de script pode ter sua própria linguagem, e o bloco é analisado de acordo com as regras de gramática do analisador de linguagem, é recomendável utilizar a sintaxe correta para a linguagem em uso. Por exemplo, se você estiver em um bloco de script do Microsoft C#, use a sintaxe de comentário C#.

Os argumentos e valores de retorno fornecidos para a função podem ser de qualquer tipo. Como os tipos W3C XPath são um subconjunto dos tipos de Common Language Runtime (CLR), a conversão de tipo ocorre nos tipos que não são considerados um tipo XPath. A tabela a seguir mostra os tipos W3C correspondentes e o tipo CLR equivalente.

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

Os tipos numéricos de CLR são convertidos em Double. O tipo DateTime é convertido em String. Os tipos IXPathNavigable são convertidos em XPathNavigator. XPathNavigator[] é convertido em XPathNodeIterator.

Todos os outros tipos lançam um erro.

Importando namespaces e assemblies

A classe XslCompiledTransform predefine um conjunto de assemblies e namespaces com suporte, por padrão, no elemento msxsl:script. No entanto, você pode usar as classes e os membros pertencentes a um namespace que não está na lista predefinida importando o assembly e o namespace no bloco msxsl:script.

Assemblies

Os dois assemblies seguintes são referenciados por padrão:

  • System.dll

  • System.Xml.dll

  • Microsoft.VisualBasic.dll (quando a linguagem de script for VB)

Você pode importar os assemblies adicionais usando o elemento msxsl:assembly. Isso inclui o assembly quando a folha de estilos é compilada. O elemento msxsl:assembly tem a seguinte definição:

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

O atributo name contém o nome do assembly e o atributo href contém o caminho para o assembly. O nome do assembly pode ser um nome completo, como "System.Data, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", ou um nome curto, como "System.Web".

Namespaces

Os seguintes namespaces são incluídos por padrão:

  • Sistema

  • System.Collection

  • System.Text

  • System.Text.RegularExpressions

  • System.Xml

  • System.Xml.Xsl

  • System.Xml.XPath

  • Microsoft.VisualBasic (quando a linguagem de script for VB)

Você pode adicionar suporte a namespaces adicionais usando o atributo namespace. O valor do atributo é o nome do namespace.

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

Exemplo

O exemplo a seguir usa um script inserido para calcular a circunferência de um círculo considerando o seu raio.

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>

Saída

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

Confira também