Bloques de scripts con msxsl:script

Nota

Los bloques de scripts solo se admiten en .NET Framework. No se admiten en .NET Core ni en .NET 5 o versiones posteriores.

La clase XslCompiledTransform admite scripts incrustados mediante el elemento msxsl:script. Cuando se carga la hoja de estilos, cualquier función definida se compila en el lenguaje intermedio común (CIL) por medio del Code Document Object Model (CodeDOM) y se ejecutan en tiempo de ejecución. El ensamblado que se genera a partir del bloque de scripts incrustado es distinto al ensamblado que se genera para la hoja de estilos.

Cómo habilitar el script XSLT

La compatibilidad con scripts incrustados es un valor XSLT opcional de la clase XslCompiledTransform. Esta compatibilidad está deshabilitada de manera predeterminada. Para habilitarla, cree un objeto XsltSettings con el conjunto de propiedades EnableScript establecido en true y pase el objeto al método Load.

Nota

El script XSLT solo se debería habilitar si necesita compatibilidad con scripts o si está trabajando en un entorno de total confianza.

Definición del elemento msxsl:script

El elemento msxsl:script es una extensión de Microsoft de la recomendación de XSLT 1.0 y tiene la siguiente definición:

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

El prefijo msxsl está enlazado al identificador URI del espacio de nombres urn:schemas-microsoft-com:xslt. La hoja de estilos debe incluir la declaración de espacio de nombres xmlns:msxsl=urn:schemas-microsoft-com:xslt.

El atributo language es opcional. Su valor es el lenguaje de código del bloque de código incrustado. El lenguaje se asigna al compilador CodeDOM apropiado utilizando el método CodeDomProvider.CreateProvider. La clase XslCompiledTransform admite cualquier lenguaje de Microsoft .NET Framework, asumiendo que en el equipo está instalado el proveedor apropiado y está registrado en la sección system.codecom del archivo machine.config. Si no se especifica un atributo language, el lenguaje predeterminado es JScript. El nombre del lenguaje no distingue mayúsculas de minúsculas, por lo que 'JavaScript' y 'javascript' son equivalentes.

El atributo implements-prefix es obligatorio. Este atributo se utiliza para declarar un espacio de nombres y asociarlo con el bloque del script. El valor de este atributo es el prefijo que representa el espacio de nombres. Este prefijo puede definirse en cualquier parte de la hoja de estilos.

Nota

Al utilizar el elemento msxsl:script, se recomienda encarecidamente que el script, independientemente del lenguaje, se coloque dentro de una sección CDATA. Puesto que el script puede contener operadores, identificadores o delimitadores para un lenguaje específico, si no está contenido en la sección CDATA, podría interpretarse erróneamente como XML. El siguiente XML muestra una plantilla de la sección CDATA en donde se puede colocar el código.

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

Funciones del script

Las funciones se pueden declarar dentro del elemento msxsl:script. Cuando se declara una función, está contenida en un bloque de scripts. Las hojas de estilos pueden contener varios bloques de scripts que funcionan independientemente unos de otros. Esto significa que si se ejecuta código desde un bloque de scripts, no podrá llamar a una función definida en otro bloque a menos que se haya declarado en el mismo espacio de nombres y con el mismo lenguaje de scripts. Puesto que cada bloque de script puede estar en su propio lenguaje, y el bloque se analiza de acuerdo con las reglas de gramática de dicho analizador de lenguaje, se recomienda utilizar la sintaxis correcta para el lenguaje que esté siendo utilizado. Por ejemplo, si está en un bloque de scripts de Microsoft C#, utilice la sintaxis de comentarios de C#.

Los argumentos suministrados y los valores devueltos a la función pueden ser de cualquier tipo. Puesto que los tipos XPath del W3C son un subconjunto de los tipos de Common Language Runtime (CLR), la conversión de tipos tiene lugar en los tipos que no se consideran un tipo de XPath. En la siguiente tabla se muestran los tipos del W3C correspondientes y el tipo CLR equivalente.

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

Los tipos CLR numéricos se convierten en Double. El tipo DateTime se convierte en String. Los tipos IXPathNavigable se convierten en XPathNavigator. XPathNavigator[] se convierte en XPathNodeIterator.

El resto de los tipos inician un error.

Importación de espacios de nombres y ensamblajes

La clase XslCompiledTransform predefine un conjunto de ensamblajes y espacios de nombres que admite de manera predeterminada el elemento msxsl:script. Sin embargo, puede utilizar las clases y los miembros que pertenecen a un espacio de nombres que no está en la lista predefinida importando el ensamblaje y el espacio de nombres del bloque msxsl:script.

Ensamblados

Se hace referencia a los dos siguientes ensamblajes de manera predeterminada:

  • System.dll

  • System.Xml.dll

  • Microsoft.VisualBasic.dll (cuando el lenguaje de scripts es VB)

Puede importar los ensamblajes adicionales utilizando el elemento msxsl:assembly. Esto incluye el ensamblaje cuando se compila la hoja de estilos. El elemento msxsl:assembly tiene la siguiente definición:

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

El atributo name contiene el nombre del ensamblaje y el atributo href contiene la ruta al ensamblaje. El nombre del ensamblaje puede ser un nombre completo como, por ejemplo, "System.Data, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", o un nombre corto como, por ejemplo, "System.Web".

Espacios de nombres

Los siguientes espacios de nombres están incluidos de manera predeterminada:

  • Sistema

  • System.Collection

  • System.Text

  • System.Text.RegularExpressions

  • System.Xml

  • System.Xml.Xsl

  • System.Xml.Xpath

  • Microsoft.VisualBasic (cuando el lenguaje de scripts es VB)

Puede agregar compatibilidad para espacios de nombres adicionales utilizando el atributo namespace. El valor del atributo es el nombre del espacio de nombres.

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

Ejemplo

En el ejemplo siguiente se utiliza un script incrustado para calcular la longitud de una circunferencia dado su radio.

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>

Salida

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

Vea también