msxsl:script を使用したスクリプト ブロック

更新 : November 2007

XslCompiledTransform クラスは、msxsl:script 要素を使用した埋め込みスクリプトをサポートしています。スタイル シートが読み込まれると、定義されているすべての関数はコード ドキュメント オブジェクト モデル (CodeDOM) によって Microsoft intermediate language (MSIL) にコンパイルされ、実行時に実行されます。埋め込みのスクリプト ブロックから生成されたアセンブリは、スタイル シートに対して生成されるアセンブリとは区別されます。

XSLT スクリプトの有効化

埋め込みスクリプトのサポートは、XslCompiledTransform クラスではオプションの XSLT 設定です。スクリプトのサポートは既定で無効になっています。スクリプトのサポートを有効にするには、EnableScript プロパティを true に設定して XsltSettings オブジェクトを作成し、そのオブジェクトを Load メソッドに渡します。

メモ :

XSLT スクリプトは、スクリプトのサポートが必要であり、完全に信頼された環境で作業している場合のみ有効にします。詳細については、「System.Xml のセキュリティに関する考慮事項」を参照してください。

msxsl:script 要素の定義

msxsl:script 要素は XSLT 1.0 勧告に対するマイクロソフトの拡張機能であり、次のように定義されます。

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

msxsl プレフィックスは urn:schemas-microsoft-com:xslt 名前空間 URI に関連付けられています。スタイル シートには xmlns:msxsl=urn:schemas-microsoft-com:xslt という名前空間の宣言が必要です。

language 属性は省略できます。その値は、埋め込みコード ブロックのコード言語です。言語は CodeDomProvider.CreateProvider メソッドを使用して、適切な CodeDOM コンパイラに対応付けられます。XslCompiledTransform クラスは、適切なプロバイダがコンピュータにインストールされ、machine.config ファイルの system.codedom セクションに登録されている限り、任意の Microsoft .NET 言語をサポートできます。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 要素内で宣言できます。関数が宣言されると、その関数はスクリプト ブロックに含まれます。スタイル シートには、相互に独立して機能する複数のスクリプト ブロックを含めることができます。このため、1 つのスクリプト ブロック内で実行しているときに、別のスクリプト ブロックで定義した関数を呼び出すことはできません。ただし、そのブロックが同じ名前空間とスクリプト言語を持つように宣言されている場合は例外です。各スクリプト ブロックは独自の言語で記述でき、ブロックはその言語に対応するパーサーの文法規則に従って解析されるため、使われている言語の正しい構文を使用することを推奨します。たとえば、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 ブロックにインポートすることにより、事前定義の一覧にない 1 つの名前空間に属するクラスとメンバを使用することができます。

アセンブリ

次の 2 つのアセンブリは既定で参照されます。

  • 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

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

埋め込みスクリプトを使用して、半径が指定された円の円周を算出する例を次に示します。

Imports System
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
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();
  }
}

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>

参照

概念

XSLT のセキュリティに関する考慮事項

その他の技術情報

XSLT 変換

動的なソース コードの生成とコンパイル