XSL/XSLTを利用したデータの変換と整列VBScriptでXMLプログラミング(3)(3/4 ページ)

» 2001年04月17日 00時00分 公開
[西谷亮マイクロソフト株式会社 ]

XSLTでのデータ変換の準備

 では、実際に単純なデータ変換を行っていくことにしましょう。非常に基本的な例を提示しますので、必要に応じて改良して試してみていただければ、より理解が深まるでしょう。また、当サイト内にXSLTの詳細に触れたコンテンツ(サンプルで覚えるXSLTプログラミング)も用意されていますので、併せてご参照ください。

 さて、今回のデータ変換では、以下のようなXML文書の構造(連載第1回目以降のものと比較すると、多少構造を単純化しています)を変更していくというシナリオに基づいて進めていきます。リスト3のXML文書には、すべてのデータがエレメントとして構成され、書籍名や価格、著者名などが記載されています。これを、あるシステムが必要なものだけを切り出す、もしくは並べ替えて利用できる状態にしようというものです。

<?xml version="1.0" encoding="UTF-8" ?>
<COLLECTION dateCreated="04-04-2001">
  <BOOK>
    <TITLE>XML 入門 - 第1巻</TITLE>
    <AUTHOR>西谷 亮</AUTHOR>
    <PUBLISHER>ABC 出版</PUBLISHER>
    <PRICE>2500</PRICE>
  </BOOK>
  <BOOK>
    <TITLE>ASP.NET 詳説</TITLE>
    <AUTHOR>西谷 亮</AUTHOR>
    <PUBLISHER>XYZ 出版</PUBLISHER>
    <PRICE>2000</PRICE>
  </BOOK>
  <BOOK>
    <TITLE>XML ハンドブック</TITLE>
    <AUTHOR>西谷 亮</AUTHOR>
    <PUBLISHER>MMM 出版</PUBLISHER>
    <PRICE>1000</PRICE>
  </BOOK>
</COLLECTION>
リスト3 変換対象のXML文書(sample.xml

 リスト3のXML文書を幾つかの形式に変換して、その結果をファイルとして保存するようにしていきましょう。まず行わなければならないのが、XSLTのコードが記述されたファイルを作成しておくことです。このファイルを幾つか用意し、プログラムから切り替えて利用するようにすれば、先に紹介した図1のようにロジックにあたるプログラムを変更しなくても、XSLTのコードを変更したりファイルを新たに用意することで、さまざまな形式に変換していくことができます。

 では、まず、書籍の名称順にソートしたXML文書の生成を行っていくことを前提に、XSLTのコードを記述していくことにしましょう。

01 : <?xml version="1.0" encoding="UTF-8" ?>
02 : <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
03 :   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
04 :   <xsl:template match="/">
05 :     <PriceList>
06 :       <xsl:for-each select="COLLECTION/BOOK">
07 :         <xsl:sort select="TITLE" data-type="text"/>
08 :         <xsl:copy>
09 :           <xsl:apply-templates select="*"/>
10 :         </xsl:copy>
11 :       </xsl:for-each>
12 :     </PriceList>
13 :   </xsl:template>
14 :   <xsl:template match="*">
15 :     <xsl:copy>
16 :       <xsl:apply-templates />
17 :     </xsl:copy>
18 :   </xsl:template>
19 : </xsl:stylesheet>

リスト4 XSLを利用した変換のためのコード その1(stylesheet1.xsl


 では、順にコードを見ていくことにしましょう。

 2行目に記述された名前空間の指定である「xmlns:xsl="http://www.w3.org/1999/XSL/Transform"」は、XSLTを利用することを明示しています。これによって XSLT Processorは、XSLTのルールに従って記述されているコードとして解釈し、必要な処理を施してくれます。

 3行目にあたる「<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />」は、変換結果の出力を指定しています。ここでは、バージョン1.0のXML文書を出力し、エンコードとしてUTF-8を指定します。これによって、出力される結果のXML文書は、UTF-8でエンコードされた文書として出力されることになります。なお、「<xsl:output method="html" version="4.0"/>」と記述すれば、HTML 4.0の文書として出力されるようにもなります。

 さて、本題のソートを行うという作業に目を向けましょう。書籍の名称でのソートを行うためには、「<xsl:sort select="TITLE" data-type="text"/>」という記述を行うことでその役割を定義します。ほかの情報に基づいてソートを行いたいような場合には、select属性に対象となる要素(もちろん、属性でも構いません)などを指定し、data-type属性にそのデータ型を与えてやります(data-typeの指定は、任意であり省略することもできます)。

 さて、ソートした結果をXML文書として出力するためのコードも記述しておかなければなりません。そのために幾つかのコードが記述されています。例えば、「<xsl:for-each select="COLLECTION/BOOK">」は、「</xsl:for-each>」と記述されている部分との間でのループ処理を定義しています。条件は、select属性によって明示されています。この例でいうと、COLLECTIONエレメントの配下にあるBOOKエレメントでのループになります。このエレメントの走査が最後までいけば終了することになります。

 あとは、ソートされたとおりに情報をそのまま書き出しますので「<xsl:copy>」という命令が用いられ、元のXML文書の情報をそのままコピーしています。もし、何らかの文字を組み合わせてデータを出力したいような場合などは、「<xsl:value-of select='TITLE'/>」という記述を用いて値をはめ込んだり、「<xsl:attribute name='TITLE'><xsl:value-of select='TITLE'/></xsl:attribute>」という書式を組み合わせて用いることで、属性としてタグに情報を書き込むといったこともできます。

 なお、このselect属性には、XPath式を用いて条件やXML文書上のパスを指定します(前述のxsl:sortにおけるselect属性も同様です)。XPathはXSLT同様にW3Cで勧告されている仕様です。本稿における本題ではありませんので、詳細についてはここでは触れませんが、必要に応じてW3CのXPathサイトやインフォテリア株式会社のホームページ上にある翻訳文書などを参考にされるとより理解が深まるでしょう。

 このようにして準備が完了すれば、あとはコードを記述するだけで変換を実現することができます。

 では、もう1つXSLTのファイルを用意しておくことにしましょう。

 この例は、与えられたXML文書に対して条件を設定し、必要な情報のみを切り出しています。具体的にいうと、PRICEエレメントの情報を判断し、2200(円)以上の値を持つものを排除しています。

01 : <?xml version="1.0" encoding="UTF-8" ?>
02 : <xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
03 :   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
04 :   <xsl:template match="/">
05 :     <LowPriceBooks>
06 :       <xsl:for-each select="*/BOOK[not(PRICE >'2200')]">
07 :     <xsl:copy>
08 :     <xsl:apply-templates select="*"/>
09 :     </xsl:copy>
10 :       </xsl:for-each>
11 :     </LowPriceBooks>
12 :   </xsl:template>
13 :   <xsl:template match="*">
14 :     <xsl:copy>
15 :     <xsl:apply-templates />
16 :     </xsl:copy>
17 :   </xsl:template>
18 : </xsl:stylesheet>
リスト5 XSLを利用した変換のためのコード その2(stylesheet2.xsl

 基本的な書式はまったく同じです。xsl:for-eachによってループ処理を定義し、必要な構造に変換した結果を出力しています。先に紹介した条件の定義は、このxsl:for-eachのselect属性によって、「≪<xsl:for-each select="*/BOOK[not(PRICE >'2200')]">」のように定義されています。この記述によって、値を判断し、データにフィルタをかけています。このように、XSLTでは、単純にデータ構造の変換を行うだけではなく、組み込まれている関数などを使用することでフィルタを行ったり、数値計算や文字列処理をあらかじめ定義しておくことができるようになっています。また、ここでは例を示しませんでしたが、MSXML 3に実装されたXSLT Processorでは、<msxsl:script>〜</msxsl:script> と記述するスクリプトブロックを使用することで、より詳細な情報処理をVB Scriptを利用して記述することができるという拡張も行われています。

 なお、表1に代表的なシンタックスとその役割をまとめておきましたので、参考までにご覧ください。また、実際にご利用になる場合は、この表に記述されていないさまざまな属性についても調べてから利用すると、より利便性が向上するでしょう。

Instruction Syntax Description
xsl:apply-imports <xsl:apply-imports /> テンプレートルールのオーバーライド(上書き)を行う
xsl:apply-templates <xsl:apply-templates
select = expression
mode = QName>
</xsl:apply-templates></xsl:apply-templates>
テンプレートの適用を行う
xsl:attribute <xsl:attribute
name = ""attribute-name""
namespace = ""uri-reference"">
</xsl:attribute>
指定された要素の属性として出力を生成する
xsl:attribute-set <xsl:attribute-set
name = qname
use-attribute-sets = qnames>
</xsl:attribute-set>
名前つきの属性の集合を定義する
xsl:call-template <xsl:call-template
name = Qname>
</xsl:call-template>
名前つきテンプレート(Named template)を指定する
xsl:choose <xsl:choose>
</xsl:choose>
条件付処理を実行
xsl:comment <xsl:comment>
</xsl:comment>
コメントとして出力する
xsl:copy <xsl:copy
use-attribute-sets = QName>
</xsl:copy>
コピーする
xsl:copy-of <xsl:copy-of
select = expression/>
結果ツリーに結果ツリーフラグメントを挿入する
xsl:element <xsl:element
name = ""element-name""
namespace = ""uri-reference""
use-attribute-sets = QName
</xsl:element>
アウトプットを指定された要素として生成する
xsl:for-each <xsl:for-each
select = expression>
</xsl:for-each>
条件に従い順次ループ処理を施す
xsl:if <xsl:if
test = boolean expression>
</xsl:if>
単純な条件分岐を実行する
xsl:import <xsl:import
href = uri-reference />
スタイルシートのインポート
xsl:include <xsl:include
href = ""URI reference""/>
スタイルシートのインクルード。この場合、定義やテンプレートルールは、インクルードする側が優先される
xsl:otherwise <xsl:otherwise>
</xsl:otherwise>
条件付処理を行う
xsl:output <xsl:output
method = ""xml"" | ""html"" | ""text""
version = nmtoken
encoding = string
/>
結果ツリーの出力方法をスタイルシート作成時に指定する
xsl:param <xsl:param
name = Qname
select = expression>
</xsl:param>
変数としてある値にバインドする
xsl:processing-instruction <xsl:processing-instruction
name = ""pi-name"">
</xsl: processing-instruction>
プロセッシングインストラクション(pi)ノードを生成する
msxsl:script * <msxsl:script
language = ""language-name""
implements-prefix = ""prefix of user's namespace"">
</msxsl:script>
グローバル変数を定義して、そしてスクリプト拡張のために作用する
xsl:sort <xsl:sort select = string-expression data-type = { "text" | "number Qname } order = { "ascending "descending><xsl:sort
select = string-expression
data-type = { "text" | "number" | Qname }
order = { "ascending" | "descending" }
/>
ソートを指定する
xsl:stylesheet <xsl:stylesheet
id = ""id""
extension-element-prefixes = ""prefixes""
exclude-result-prefixes = ""prefixes""
version = ""number"">
</xsl:stylesheet>
スタイルシートは、XML文書内にxsl:stylesheetエレメントとして表される
xsl:template <xsl:template
name= Qname
match = pattern
priority = ""number""
mode = Qname
</xsl:template>
テンプレートルールを指定する
xsl:text <xsl:text
disable-output-escaping = ""yes"" | ""no"">
</xsl:text>
アウトプットでテキストを生成する。リテラル文字も利用可
xsl:transform <xsl:transform
id = id
extension-element-prefixes = tokens
exclude-result-prefixes = tokens
version = number>
<!-- Content: (xsl:import*, top-level-elements) -->
</xsl:transform>
xsl:stylesheet と同義語
xsl:value-of <xsl:value-of
select = expression
disable-output-escaping = ""yes"" | ""no""
</xsl:value-of>
指定された値をテキストとして生成
xsl:variable <xsl:variable
name = Qname
select = expression>
</xsl:variable>
変数としてある値にバインドする
xsl:when <xsl:when
test = boolean expression>
</xsl:when>
条件付処理を実行する
xsl:with-param <xsl:with-param
name = Qname
select = expression>
</xsl:with-param>
テンプレートにパラメータを渡す。

 では、実際にこれらのXSLTのコードを利用して元のXML文書の変換を行っていくことにしましょう。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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