連載
» 2002年03月08日 00時00分 UPDATE

XSLTスタイルシート書き方講座(応用編 最終回):ファイル出力とXSLT機能拡張

[奥井康弘, 吉田稔, 青木秀起,株式会社日本ユニテック]

前回の「XMLデータの埋め込みと相互参照」では、複数のXMLデータを操作する方法と、相互参照機能を使って必要なデータのみを抽出する方法を考えました。本連載の最後となる今回は、結果ツリーをファイルに出力する方法、およびXSLTの規格にない命令や関数を拡張して使用する方法を説明します。XSLTでは命令や関数の拡張を許可しています。今回は、いくつかのXSLTプロセッサとその拡張機能も紹介します。

結果ツリーをファイル出力する

 本連載では、これまで読者がXSLTの変換結果をすぐに確かめられるよう、Internet Explorer 5(以下IE 5)を使って、HTMLの結果ツリーをWebブラウザに直接表示させてきました。しかしXSLTは、XMLデータを、XML形式やHTML形式、テキスト形式などのファイルへのバッチ的な変換の際にも使用されます。そうした用途のためのXSLT命令が、結果ツリーのファイル出力を制御するxsl:output要素です。

図1 xsl:output要素の位置付け 図1 xsl:output要素の位置付け

xsl:output要素の書き方

 XSLTでは、結果ツリーを書き出すファイルの出力形式の指定などを、xsl:output要素によって行います。xsl:output要素は、トップレベル要素であるxsl:stylesheet要素の子要素です。xsl:output要素の書き方を以下に示します。

<xsl:output
  method = "xml" | "html" | "text" | "他の出力形式"
  version = "バージョン番号"
  encoding = "符号化方式"
  omit-xml-declaration = "yes" | "no"
  standalone = "yes" | "no"
  doctype-system = "公開識別子"
  cdata-section-elements = "要素名のリスト"
  indnent = "yes" | "no"
  media-type = "MIMEタイプ" />
リスト1 xsl:outputの書き方
属性 機能
method 出力されるデータ形式を指定(HTML、XML、テキスト、ほかの出力形式)
version XML形式またはHTML形式の出力データのバージョンを指定
encoding 符号化方式を指定
omit-xml-declaration XML宣言を出力するかどうかを指定。属性値が“yes”の場合、XML宣言は出力されない
standalone スタンドアロン宣言を出力
doctype-system DOCTYPE宣言を出力
cdata-section-elements 内容のテキストデータをCDATAセクションとして出力したい要素の名前のリストを指定
indent 字下げのための空白を出力するかどうかを指定
media-type 出力データのMIMEタイプを指定
表1 xsl:output要素の属性

MSXSLをインストールしておく

 これからxsl:output要素の使い方を、サンプルプログラムを使って説明します。ただし、このサンプルプログラムはバッチ式にXSLT変換をさせるものですので、まずコマンドラインから打ち込めるXSLT変換ユーティリティ“msxsl.exe”をインストールしておきます。msxsl.exeは、マイクロソフトのMSDN Libraryから無償でダウンロードできます。

xsl:output要素を使ってみる

 ではサンプルを見ながらxsl:output要素の使い方を学びましょう。リスト2のXMLデータを見てください。

<?xml version="1.0" encoding="shift_jis"?>
<customer>
  <name>秋本太郎</name>
</customer>
リスト2 入力XMLデータ(customer.xml)

 このXMLデータの“customer”要素と“name”要素を、それぞれ“顧客”要素と“氏名”要素に変換し、別のXMLファイルにしてみましょう。この場合の変換ルールを記述したXSLTスタイルシートをリスト3に示します。

<?xml version="1.0" encoding="shift_jis"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" encoding="shift_jis"/>
    <xsl:template match="/">
      <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="customer">
      <顧客>
        <xsl:apply-templates/>
      </顧客>
    </xsl:template>
    <xsl:template match="name">
      <氏名>
      <xsl:value-of select="."/>
    </氏名>
  </xsl:template>
</xsl:stylesheet>
リスト3 ファイル出力制御のためのスタイルシート(output.xsl)

 リスト3のxsl:output要素の部分をもう一度ご覧ください。XML形式のデータを出力しますので、method属性値に“xml”を指定しています。またencoding属性によって、出力ファイルの文字コードとして“shift_jis”を指定しています。

<xsl:output method="xml" encoding="shift_jis"/>

 では、MS-DOSのコマンドウィンドウでMSXSLを実行させてみましょう。XMLデータやスタイルシートを同じディレクトリに置いてから画面1のように入力してください。

画面1 ユーティリティを使ってXMLデータを変換・出力する 画面1 ユーティリティを使ってXMLデータを変換・出力する

 MSXSLの第1パラメータとして、入力XMLファイル名(customer.xml)を、第2パラメータとして、適用するスタイルシートファイル名(output.xsl)を指定します。オプション機能のファイル出力を指示するキーワード“-o”に続いて、出力ファイル名(customerj.xml)を指定します。出力されたファイルをIE 5で開くと画面2のとおりになります。

画面2 xsl:output要素による出力制御結果(customerj.xml) 画面2 xsl:output要素による出力制御結果(customerj.xml)

命令要素や関数の拡張機能

 XSLTには、XSLTの規格以外の命令や関数をベンダやユーザーが独自に追加して機能を拡張する仕組みが備わっています。

XSLTの命令を拡張する

 XSLTの規格では変換処理を制御する命令が要素として定義されています。それらに加えてベンダやユーザーは、必要とする命令を新しい要素として定義することができます。こうした要素を拡張要素(extension element)といいます。

 代表的なXSLTプロセッサが実装している拡張要素を以下に示します。

プロセッサ 開発 拡張要素
SAXON Michael H. Kay saxon:assign(変数へ値の割り当て)
saxon:doctype(DTDの生成)
saxon:entity-ref(エンティティの生成)
saxon:functionとsaxon:scriptとsaxon:return(拡張関数の定義)
saxon:groupとsaxon:item(グループ化)
saxon:handler(テンプレート)
saxon:output(複数ファイルの処理)
saxon:preview(大きなXMLデータの分割)
saxon:while(繰返し)
Xalan Apache XML Project redirect:openとredirect:write、
redirect:close(複数ファイルの処理)
XT James Clark xt:document(複数のファイル処理)
表1 XSLTプロセッサとその拡張要素

 上記の拡張要素の表記方法から分かるとおり、拡張要素は、拡張要素が属する名前空間とその名前空間と関連付けられた接頭辞を使って定義します。拡張要素の定義は次の二通りの方法で行えます。

  • xsl:stylesheet要素にextension-element-prefixes属性を付加して定義する
  • 拡張要素にextension-element-prefixes属性を付加して定義する

 例えば、SAXONプロセッサの拡張要素saxon:entity-refを使って、エンティティ“&nbsp;”を生成するとします。この拡張要素は、xsl:stylesheet要素においてリスト4のように定義できます。

<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://icl.com/saxon"
extension-element-prefixes="saxon">
  ……
  <saxon:entity-ref name="nbsp"/>
  ……
</xsl:stylesheet>
リスト4 拡張要素の名前空間接頭辞をxsl:stylesheet要素のところで宣言する

 リスト4において“saxon”は、extension-element-prefixes属性によって拡張要素のための名前空間接頭辞として宣言されています。従って、XSLTプロセッサは、saxonという接頭辞で修飾された要素であるsaxon:entity-ref要素を、拡張要素と見なして処理します(注1)。

(注1)もちろん、saxon:entity-ref要素自体にextension-element-prefixes属性を付加して拡張要素として定義することもできます。


XSLTの関数を拡張する

 XSLTのスタイルシートで使用される関数の名前で名前空間接頭辞がないものは、XSLTまたはXPathのビルトイン関数です。一方、名前空間接頭辞が付加された名前の関数は、ベンダやユーザーが新たに追加した拡張関数と見なされます。従って次のように記述した場合、名前空間接頭辞(この場合はdx)が関数MyDateに付加されていますので、XSLTプロセッサは、MyDate()を拡張関数と見なします。

dx:MyDate()

 なお、XSLT1.0は、要素や関数の拡張機能の実装を定義するメカニズムを定めていません。従って拡張機能を定義する場合、用いるXSLTプロセッサの仕様を調べる必要があります。例えばMSXML3プロセッサでは、msxsl:script要素によって拡張機能を定義します。

 MSXML3プロセッサを例にして拡張関数の定義の仕方を示しましょう。リスト2と同様なXMLデータを読み込み、それに日付を付加した後、Webブラウザ表示させるスタイルシートを書いてみます(リスト5)。

<?xml version="1.0" encoding="shift_jis"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dx="http://www.utj.co.jp/dx">
<msxsl:script xmlns:msxsl="urn:schemas-microsoft-com:xslt" language="JavaScript" implements-prefix="dx">
  function MyDate() {
    dt = new Date();
    m = dt.getMonth()+1;
    d = dt.getDate();
    return m+"月"+d+"日"}
</msxsl:script>
<xsl:output method="xml" encoding="shift_jis" indent="yes"/>
<xsl:template match="/">
  <html>
    <body>
      <p>
        <xsl:value-of select="dx:MyDate()"/>
        のお客様は、
        <xsl:value-of select="."/>様です。
      </p>
    </body>
  </html>
</xsl:template></xsl:stylesheet>
リスト5 MSXML3プロセッサによって拡張関数を定義する例

 まず、xsl:stylesheet要素で、ユーザーが定義する拡張関数のための名前空間を宣言します。例では、宣言された名前空間の接頭辞を“dx”としています。

xmlns:dx="http://www.utj.co.jp/dx"

 次にMSXMLによる拡張要素であるmsxsl:script要素で、拡張関数MyDate()を定義します。msxsl:script要素の詳しい説明は省略しますが、リスト5から分かるとおり、例ではJavaScriptで拡張関数が記述されていること、拡張関数が属する名前空間の接頭辞が“dx”であることが宣言されています(注2)。

(注2)msxsl:script要素はマイクロソフトが独自に拡張した要素です。従って、msxsl:script要素は、前項で述べたようにextension-element-prefixes属性を使って拡張名前空間として宣言する必要があると思われるかもしれませんが、そうなってはいません。これは、XSLT規格によると「XSLTの名前空間ではない、何らかの名前空間に属する要素は無視する」と定められており、トップレベル要素(xsl:stylesheet要素直下の子要素)はこの仕様に該当するからです。詳しくはW3CによるXSLTの仕様書、またはXSLTの解説書を見てください。


<msxsl:script xmlns:msxsl="urn:schemas-microsoft-com:xslt" language="JavaScript" implements-prefix="dx">
  function MyDate() {
    dt = new Date();
    m = dt.getMonth()+1;
    d = dt.getDate();
    return m+"月"+d+"日"}
</msxsl:script>

 msxsl:script要素の内容を見ると分かるとおり、拡張関数MyDate()は、まずシステム日付を取得し、それを「○月△日」の書式に直してから関数値として返却します。JavaScript言語の記述の仕方は、スクリプト言語の解説書を見てください。

 リスト5のスタイルシートをリスト2のXMLデータに関連付けて構造変換し、それをWebブラウザ表示させると、画面3のとおりになります。本稿を執筆している日付が表示結果に含められました。

画面3 拡張関数を使ったサンプルのWebブラウザ表示結果 画面3 拡張関数を使ったサンプルのWebブラウザ表示結果

まとめ

 全7回の連載で、XSLTの概要からプログラミング、拡張機能まで解説しました。今回の連載で取り上げたのはそのほんの一部でしたが、ノード生成や文字列の操作など、このほかにも便利な関数や命令がまだまだたくさんあります。強力な機能満載のXSLTは、今後さらに利用されてゆくことでしょう。

本記事は、日本ユニテック発行のXMLテクノロジー総合情報誌「Digital Xpress」に掲載された、XSLT特集「XSLTの実力を探る!」の内容をもとに、加筆修正したものです。


Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。