XMLマスターポイントレッスン
      ~ プロフェッショナル(アプリケーション開発)編 ~
第4回 XSLTスタイルシートによるXML文書の変換

インフォテリア株式会社  教育部 木村 達哉

今回は、「XMLマスター:プロフェッショナル(アプリケーション開発)」認定試験のセクション3で出題される、XSLT関連問題のポイントについて解説します。セクション3は出題範囲が広く、ここで紹介する問題はほんの一例にすぎませんが、解説を参考に、学習すべきポイントをしっかりと押さえてください。

セクション3のポイント

セクション3で出題されるXSLT関連の問題を解くうえで必要となるのは、提示されたXML文書とXSLTスタイルシートを基に、変換結果を導き出す知識/能力です。例えば、特定の機能を持つ要素に関する知識が問われる問題もあれば、テンプレート※1の使用方法を含む、XSLTについての総合的な理解度を試される問題もありますので、体系的にバランス良く学習を進めておくことが重要です。

※1  XSLTスタイルシートに記述する、XML文書の変換ルール。XSLTスタイルシートには、テンプレートのほかに、変換した文書の出力方法を記述する。

JavaによるXSLT変換

Javaを使用してXSLT変換を行う方法について簡単に説明しておきましょう。と言っても、J2SE 5.0には、XMLを処理するための標準API「JAXP(Java API for XML Processing)」が含まれており、これを使えばXSLT変換を行うプログラムを簡単に作ることができます。リスト1に示すのが、JAXPを用いて作成したXSLT変換を行うプログラムの例です。

リスト1:Java(JAXP)を使用してXSLT変換を行うプログラム(XSLTExec.java)


import java.io.FileOutputStream;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class XSLTExec {
   public static void main(String[] args) {
      if (args.length < 3) {
         System.out.println(
            "usage: XSLTExec XML-file XSLT-stylesheet Output-file");
         return;
      }
      String xml = args[0];
      String xslt = args[1];
      String output = args[2];
      try {
         TransformerFactory tf = TransformerFactory.newInstance(); ----- (2)
         Transformer tr = tf.newTransformer(new StreamSource(xslt)); -- (1)
         tr.transform(new StreamSource(xml),
         new StreamResult(new FileOutputStream(output)));
 
         System.out.println("Output to " + output);
      } catch (Exception e) {
         System.out.println(e);
      }
   }
}

  このプログラムは、第1引数に指定されたXML文書を第2引数に指定されたXSLTスタイルシートを使って変換し、その結果を第3引数に指定されたファイルに出力します。

  リスト1からもわかるように、JAXPを使用してXSLT変換を行う場合、クラスjavax.xml.transform.Transformerのインスタンスを生成します(リスト1-(1))。同インスタンスを生成する際には、先にファクトリ・クラスjavax.xml.transform.TransformerFactoryのインスタンスを生成しておく必要があります(リスト1-(2))。

  このように、JavaでXSLT変換を行う際には、一般にJAXPを使用します。学習を進めるうえでは、XSLTスタイルシートによってどのような変換結果が得られるかといったことだけでなく、こうしたことも理解していれば、学んだ知識をすぐに実務で生かせるはずです。なお、XSLTスタイルシートの記述内容を理解するには、既存のXSLTスタイルシートを眺めるだけではなく、実際にさまざまなスタイルシートを自分で作成し、変換を行ってみることをお勧めします。

  それでは、XSLT関連の問題のポイントに話を進めましょう。以降では、XSLTに関する例題/解答を提示するとともに、その問題でポイントとなる個所を解説していきます。

●XSLT関連の出題例――その(1)

  次の《XML文書》を《XSLTスタイルシート》によってXSLT変換したときの出力結果として、正しいものを選択してください。ただし、使用するXSLTプロセッサは、変換結果を文書のかたちで出力できるものとします。

《XML文書》

<Rensai>
  <Title section="1">DOM/SAXの基本仕様</Title>
  <Title section="2">DOM/SAXプログラミング</Title>
</Rensai>

《XSLTスタイルシート》

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="text" />
  <xsl:strip-space elements="Rensai" />
 
  <xsl:template match="/">
    <xsl:apply-templates select="Rensai//* | Rensai//text() | Rensai//@*" />
  </xsl:template>
  <xsl:template match="* | text() | @*">
    <xsl:value-of select="name(.)" />[<xsl:value-of select="." />]
    <xsl:text>&#xA;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

●選択肢
A.

Title[]
Title[]
[DOM/SAXの基本仕様]
[DOM/SAXプログラミング]
section[1]
section[2]

B.

Title[DOM/SAXの基本仕様]
Title[DOM/SAXプログラミング]
[DOM/SAXの基本仕様]
[DOM/SAXプログラミング]
section[1]
section[2]

C.

Title[]
[DOM/SAXの基本仕様]
section[1]
Title[]
[DOM/SAXプログラミング]
section[2]

D.

Title[DOM/SAXの基本仕様]
section[1]
[DOM/SAXの基本仕様]
Title[DOM/SAXプログラミング]
section[2]
[DOM/SAXプログラミング]

●解答
D

●解説
  問題で提示されているXSLTスタイルシートには、2つのテンプレートが含まれていますが、XSLTの仕様では、必ずルート・ノード用のテンプレート(<xsl:template match="/">で始まるテンプレート)から処理を始めるように規定されています。上のXSLTスタイルシートのルート・ノード用テンプレートでは、処理対象となるXML文書の中から、次のノードを選択します(要素xsl:apply-templatesの属性selectの値にあるパイプ[|]は、ノードの和集合を表す記号です)。

●要素Rensaiの子孫となるすべての要素ノード
●要素Rensai以下のすべてのテキスト・ノード
●要素Rensai以下のすべての属性ノード

  そして、ルート・ノード用テンプレートで選択された上記の各ノードは、もう1つのテンプレート(<xsl:template match="* | text() | @*">で始まるテンプレート)によって処理されます。このテンプレートが行う処理は、それぞれのノードについて、以下のような形式で文字列を出力するというものです。

《ノードの名前》[《ノードの値》]

  この問題に正答するには、提示されたXSLTスタイルシートとXML文書から上記のような情報を読み取ったうえで、さらに次のような事柄を理解している必要があります。

●ノードの名前は、どのような形式の文字列で取得できるのか
●ノードの値は、どのような形式の文字列で取得できるのか
●複数ノードの処理は、どのような順序で行われるのか

  これらのポイントについて、以下に説明しておきましょう。

  まず、ノードの名前に関してですが、ご存じのとおり、XSLTは、XPathのデータ・モデルを拡張したものです。XPathでは、要素ノードやテキスト・ノードなど、7種類のノードが定められていますが、ルート・ノードとテキスト・ノード、コメント・ノードには、「名前」の概念がありません。これは、XPathの拡張モデルであるXSLTでも同様です。名前のあるノードからは、名前をそのまま文字列として取得できますが、名前がないものに関しては何も取得できないのです。

  また、ノードの値を取得する際の形式は、以下のように、ノードの種類によって異なります。

要素ノード:そのノードに属する要素の内容文字列を連結した状態
属性ノード:XML 1.0に従って正規化された属性値
テキスト・ノード:テキスト・ノードの文字列値

  さらに、複数ノードを処理する際の順番は、XPathの規定に準拠します(テンプレートにノードを記述した際の順番は関係ありません)。XPathでは、基本的に、XML文書中でノードが出現する順番に従って処理を行うことが定められているので、問題のXML文書の場合には、「要素ノード→属性ノード→テキスト・ノード」の順に処理が行われることになります※2

  以上のことからもわかるように、XSLT関連の問題に臨む際には、XSLTの知識だけではなく、XPathのデータ・モデルに関する知識も必要となります。

  なお、ここでは取り上げませんでしたが、試験では、要素xsl:strip-space、要素xsl:preserve-spaceによる空白文字の制御方法や、名前空間を使用したXML文書の変換方法なども出題されます。そのほか、出題頻度が高く、実務でも重要なポイントとなる項目を以下に列挙しておくので、これらに関してもしっかりと学習しておいてください。

●テンプレートの競合/モード/インクルード/インポート
●要素xsl:variable、または要素xsl:paramによる、変数を使用した処理
●要素xsl:keyと関数keyによる、キー(ノードの識別情報)を使用した処理
●関数documentによる、複数のXML文書の処理

※2  ただし、1つの要素に複数の属性が記述されている場合、属性ノードの処理順序はXSLTプロセッサの実装に依存する。

●XSLT関連の出題例――その(2)

  次の《XML文書》を《XSLTスタイルシート》によってXSLT変換したときの出力結果として、正しいものを選択してください。ただし、XSLTプロセッサは、変換結果を文書として出力できるものとします。また、改行やインデントは考慮しません。

《XML文書》

<Rensai>
  <Title category="XML">XMLマスターポイントレッスン ~ プロフェッショナル(アプリケーション開発)編 ~ </Title>
  <SubTitle section="1">DOM/SAXの基本仕様</SubTitle>
  <SubTitle section="2">DOM/SAXプログラミング</SubTitle>
</Rensai>

《XSLTスタイルシート》

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="/">
    <xsl:apply-templates />
  </xsl:template>
 
  <xsl:template match="*|text()|@*">
    <xsl:copy>
      <xsl:apply-templates />
    </xsl:copy>
  </xsl:template>
 
  <xsl:template match="Rensai">
    <xsl:copy>
      <xsl:apply-templates select="Title/@category" />
      <xsl:apply-templates />
    </xsl:copy>
  </xsl:template>
 
  <xsl:template match="@category">
    <xsl:element name="category">
      <xsl:value-of select="." />
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

●選択肢
A.

<Rensai>
  <Title category="XML">XMLマスターポイントレッスン ~ プロフェッショナル(アプリケーション開発)編 ~ </Title>
  <SubTitle section="1">DOM/SAXの基本仕様</SubTitle>
  <SubTitle section="2">DOM/SAXプログラミング</SubTitle>
</Rensai>

B.

<Rensai>
  <category>XML</category>
  <Title category="XML">XMLマスターポイントレッスン ~ プロフェッショナル(アプリケーション開発)編 ~ </Title>
  <SubTitle section="1">DOM/SAXの基本仕様</SubTitle>
  <SubTitle section="2">DOM/SAXプログラミング</SubTitle>
</Rensai>

C.

<Rensai>
  <category>XML</category>
  <Title>XMLマスターポイントレッスン ~ プロフェッショナル(アプリケーション開発)編 ~ </Title>
  <SubTitle>DOM/SAXの基本仕様</SubTitle>
  <SubTitle>DOM/SAXプログラミング</SubTitle>
</Rensai>

D.

<Rensai>
  <category>XML</category>
  <Title category="XML" />
  <SubTitle section="1" />
  <SubTitle section="2" />
</Rensai>

E.

<Rensai>
  <category>XML</category>
  <Title />
  <SubTitle />
  <SubTitle />
</Rensai>

F.
何も出力されない

●解答
C

●解説
  この問題でポイントとなる部分は、2つあります。

  1つは、要素xsl:apply-templatesにおいて、属性selectが省略された場合のXSLTプロセッサの動作です。この場合、XSLTプロセッサはすべての子ノードに対して処理を行います。ただし、属性ノードは要素の子ノードではないため、処理対象には含まれません。

  もう1つのポイントは、要素xsl:copyの役割です。同要素は、その時点での処理対象ノードを複製します。ここで注意が必要なのは、対象要素ノードの子ノードや属性ノードは複製されないという点です。

  以上の点を踏まえ、問題のXSLTスタイルシートに記述されている処理内容を読み解くと、次のようになります。

●ルート・ノード用のテンプレート(<xsl:template match="/">で始まるテンプレート)では、要素Rensaiを処理対象として選択する。
●要素Rensaiのノード用テンプレート(<xsl:template match="Rensai">で始まるテンプレート)では、まず要素xsl:copyによって要素Rensaiのノードを複製する。次に、要素Titleの属性categoryを処理対象として選択する。最後に、すべての要素Title、SubTitleを処理対象として選択する。
●属性categoryのノード用テンプレート(<xsl:template match="@category">で始まるテンプレート)では、要素categoryを生成し、その内容として属性categoryの値「XML」を使用する。
●要素Title、およびSubTitleのノード用テンプレート(<xsl:template match="*|text()|@*">で始まるテンプレート)では、それぞれのノードを複製した後、その子ノード(テキスト・ノード)に対して処理(この場合は複製)を行う。ただし、属性は処理しない。


ページトップへ▲

XMLマスターポイントレッスン ~ プロフェッショナル(アプリケーション開発)編 ~ 記事一覧へ戻る

HOMEへ戻る