[Home] [Kuri] [Sysad] [Internet?] [Blog] [Java] [Windows] [Download] [Profile] [Flash] [+]

Xalan で XSLT を使ってみる

私はとあるファームウェアを開発しています。検証が終り、お客様に出せる ものができると、リリースメモや設計通知書というものを書いて、ファーム ウェアとともに工場などにリリースしています。
今までは、リリースメモなどの文書を
MS 社の Word を使用して書いていました。 しかし、Word の文書はバイナリ形式で、どのようなフォーマットになって いるのかわかりません。ですから、中の情報を単に抜き出したいだけでも Word を起動する必要があります。 (玄人さんだとうまいことできるのかもしれませんが、Windows のパワー ユーザではない私にはわかりません。)
しかし、Word をスムースに使用するためにはある程度のマシンパワーが 必要になりますし、そもそも UNIX を主に使い、コマンドラインで作業を するのに慣れてしまっている私にとっては、GUI でしか操作できないという のは使いづらいのでした。
さて、ここのところ XML が非常に注目され、また様々なところで使用されて いると(風の便り?で)聞きました。XML ですとテキストベースですし、XML を 扱うライブラリ等が世の中にいろいろ出回っているようですので、Word を 捨てて XML にしてしまえばいいのではないか考えました。
ここでは、 XSLT(eXtensible Stylesheet Language Transformations) という、 XML 文書を変換するための言語を用いて、文書を Word から XML に移行 させるまでの過程(苦労?)を示します。

目次


1. XSLT にたどり着くまで

当初、リリース情報を XML で記述し、それを LaTeX や HTML に変換する ものを(DOM あるいは SAX を用いて)自力で作ろうと考えました。
しかし、私はものごとにとりかかるまでに非常に時間がかかります。すぐに 試せるものでないとすぐに作れないように思われました。 そこで、すでに似たようなものがないか探すことから始めました。
で、探してみたところ、
SmartDoc なるものを見つけました。 これは、XML で書いた文書を TeX や HTML, JavaHelp などに変換してくれ る優れものです。早速使ってみたのですが、思うような TeX のコードを出力 させることができません。いろいろ試行錯誤したのですがうまくいかず、 泣く泣く SmartDoc の使用を断念しました。
# SmartDoc が悪いというわけではありません。少なくとも新規で書くドキュ メントには使おうかなと思っております。
XML に関係する本や雑誌をぺらぺらとめくっていますと、XSLT という便利 そうなものに出会いました。
具体的には JavaWorld に載っていたのですが、その例を見ているだけで 比較的簡単に LaTeX や HTML に変換できるのではないかと思われました。
# わたしの重い腰が少し上がりました。

2. XSLT とは

XSLT とは、スタイルシートにしたがって、ある XML 文書を別の XML 文書に 変換するための言語です。
XSL という、スタイルシート を XML で表現するための言語から、XML の変換機能が分離独立してできた 言語のようです。
何はともあれ、以降の例を見てください。
# ようするに、よくわかっていません。理解しなくても使えるところがなんとも…

3. 環境

OS は FreeBSD-4.1R です。JDK はパッケージになっている 1.1.8 です。
XSLT プロセッサには
Xalan を使用しました。この時のバージョンは 1.2.2 でした。
# おそらくは Windows などの JDK1.2 以降でも問題ないと思います。

4. LaTeX 用のスタイルシートを作る

まず、もととなる XML 文書の DTD を以下のように定義します。

  <!ELEMENT releaseMemo	(machine,version,problem+,correction+,releaseDate)>
  <!ELEMENT machine	(#PCDATA)>
  <!ELEMENT version	(#PCDATA)>
  <!ELEMENT problem	(#PCDATA)>
  <!ATTLIST problem	index #IMPLIED>
  <!ELEMENT correction	(#PCDATA)>
  <!ATTLIST correction	index #IMPLIED>
  <!ELEMENT releaseDate	(#PCDATA)>

releaseMemo がルート・ノードになります。 この中に、machine, version, problem, correction, releaseDate という タグを順に書いていく必要があると、1行目で定義しています。
machine などは1つだけ必要になります。problem など + が ついているものは、1つ以上必要であることを表しています。 上記の例ではありませんが、例えば * だと0個以上、? だと0か1個 になります。
machine は機種名、version はバージョン名、problem は 不具合内容、correction は変更内容、relaseDate は リリース年月日を表します。
problemcorrection には index という属性が付加できます。
以下に、上記 DTD に従った XML 文書の例を示します。

  <?xml version="1.0"?>
  <releaseMemo>
    <machine> Machine-1 </machine>
    <version> 1.1 </version>
    <problem index="a."> シュート成功率が悪い。</problem>
    <problem index="b."> すぐにばてる。</problem>
    <correction index="a."> 眼鏡の度を修正。</correction>
    <correction index="b."> メモリリークを修正。</correction>
    <correction index="c."> フックシュートに対応。</correction>
    <releaseDate>2001年5月30日</releaseDate>
  </releaseMemo>

さて、これを以下のような LaTeX のコードに変換したいとします。

\documentstyle[a4j]{jarticle}
\pagestyle{empty}
\begin{document}
\begin{center}
  {\large リリースメモ}
\end{center}

\begin{tabular}{p{4cm}p{11cm}}
  機種名: & machine \\
  バージョン: & version \\
  問題点: \\
      & problem の index と problem \\
      & problem の index と problem \\
              :
              :
  修正内容:\\
      & correction の index と correction \\
      & correction の index と correction \\
              :
              :
  リリース日: & releaseDate \\
\end{tabular}
\end{document}

上記の赤字のところに各値を埋め込みたいということです。
これをもとに XSLT スタイルシートにしたものが以下になります。

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" encoding="EUC-JP"/>
<xsl:template match="releaseMemo">

\documentstyle[a4j]{jarticle}
\pagestyle{empty}
\begin{document}
\begin{center}
  {\large リリースメモ}
\end{center}

\begin{tabular}{p{4cm}p{11cm}}
  機種名: &amp; <xsl:value-of select="machine"/>  \\
  バージョン: &amp; <xsl:value-of select="version"/>  \\
  問題点: \\
      <xsl:apply-templates select="problem"/>
  修正内容:\\
      <xsl:apply-templates select="correction"/>
  リリース日: &amp; <xsl:value-of select="releaseDate"/> \\
\end{tabular}
\end{document}
</xsl:template>

<xsl:template match="problem">
   &amp; <xsl:value-of select="attribute::index/>
             <xsl:value-of select="."/> \\
</xsl:template>

<xsl:template match="correction">
   &amp; <xsl:value-of select="attribute::index/>
             <xsl:value-of select="."/> \\
</xsl:template>

</xsl:stylesheet>

最初の2行は欠かせません。2行目が XSLT スタイルシートのルート・ノード になります。ここでは、ネームスペースの接頭辞を xsl としています。 (xsl じゃなくても動作的には支障がないそうです。)
3行目の xsl:output は、出力フォーマットを指定しています。method 属性で フォーマットを指定できます(xml, html, text あるいはその他の名前)。 また、encoding メソッドで文字コード名を指定できます。 EUC-JP にしているのは、単にこちらの都合です。
4行目以降(〜23行)の xsl:template が、ルート・ノード releaseMemo に対する テンプレート・ルールになります。もとの文書の releaseMemo の部分がこの テンプレートに置き換わります。
このテンプレート・ルールに含まれる xsl:value-of は、属性 select で指定した 内容に置き換えるという意味になります。指定の仕方は
XPath で定義された式になります。 例えば属性 select が "machine" の場合、releaseMemo にある machine タグの 内容に置き換わります。"." ですとカレントノード、"attribute::index" ですと カレントノードの属性 index の内容になります。詳しくは XPath の定義をご覧 ください。
xsl:apply-templates は、別の xsl:template で指定したテンプレート・ルール を適用するという意味になります。属性 select で、テンプレート・ルールを 指定します。例えば "problem" の場合、25行目のテンプレート・ルールを指定 していることになります。
あと、& はそのまま書けませんので、&amp; と書いておきます。

5. LaTeX に変換してみる

さて、実際に Xalan を用いて変換してみます。
まず、Xalan に含まれる xalan.jar および xerces.jar を適当な場所に置いて CLASSPATH に含めます。(JDK1.2 以降でしたら、lib/ext 以下に放り込むだけ でいいと思います。)
次に、変換するためのものを作ります。

import org.apache.xalan.xslt.*;
import org.xml.sax.*;

public class doctrans {
    public static void main(String[] a) {
	if(a.length != 2) {
	    System.err.println("Usage: java doctrans XML XSL");
	    System.exit(1);
	}

	try {
	    XSLTProcessor proc = XSLTProcessorFactory.getProcessor();
	    proc.process(new XSLTInputSource(a[0]),
		new XSLTInputSource(a[1]),
		new XSLTResultTarget(System.out));
	} catch(Exception e) {
	    e.printStackTrace();
	}
    }
}

ご覧の通り、いたって簡単です。
第1引数にもとの XML 文書を、第2引数に XSLT スタイルシートを指定します。 あとは XSLTProcessor のオブジェクトを作成し、process メソッドで変換した 内容を標準出力に出力しているだけです。
ただし、これをそのまま実行しても変換してくれません。以下のように叱られて しまいました。 (ちなみに EUC で書いていましたが、SJIS などにしても同様でした。)

% java doctrans test1.xml temp1.xml
file:///some/where/test/test1.xml; Line 11; Column 14
XSL Error: Could not parse test1.xml document!
XSL Error: SAX Exception
...後略

どうやら、日本語の文字コードだと叱られてしまいます。というか、Unicode でないといけないようです。そこで、
文字コードをこれで 変換 してから実行してみました。

% java enctrans test1.xml JISAutoDetect UTF8 > test1.xml.utf8
% java enctrans temp1.xml JISAutoDetect UTF8 > temp1.xml.utf8
% java doctrans test1.xml.utf8 temp1.xml.utf8

\documentstyle[a4j]{jarticle}
\pagestyle{empty}

\begin{document}
\begin{center}
{\large リリースメモ}\\
\end{center}
\begin{tabular}{p{4cm}p{11cm}}
  機種名: &  Machine-1  \\
  バージョン: &  1.1  \\
  問題点: \\
    
   & a. シュート成功率が悪い。 \\

   & b. すぐにばてる。 \\

  修正内容: \\
    
   & a. 眼鏡の度を修正。 \\

   & b. メモリリークを修正。 \\

   & c. フックシュートに対応。 \\

  リリース日: & 2001年5月30日 \\
\end{tabular}
\end{document}

出力の方は、ちゃんと encoding で指定した EUC-JP になります。

6. HTML の場合

HTML の場合の XSLT テンプレートを以下のようにします。

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" encoding="SJIS"/>
<xsl:template match="releaseMemo">
<html>
<head>
<title>Release Memo</title>
<meta http-equiv="Content-Type" content="text/html; charset=x-sjis"/>
</head>
<body>
<h1>リリースメモ</h1>
<table>
  <tr><th align="left">機種名:</th>
      <td><xsl:value-of select="machine"/></td>
  </tr>
  <tr><th align="left">バージョン</th>
      <td><xsl:value-of select="version"/></td>
  </tr>
  <tr><th align="left">問題点:</th>
  </tr>
    <xsl:apply-templates select="problem"/>
  <tr><th align="left">修正内容:</th>
  </tr>
    <xsl:apply-templates select="correction"/>
  <tr><th align="left">リリース日:</th>
      <td><xsl:value-of select="releaseDate"/></td>
  </tr>
</table>
</body>
</html>
</xsl:template>

<xsl:template match="problem">
  <tr><td></td>
      <td><xsl:value-of select="attribute::index"/>
          <xsl:value-of select="."/></td>
  </tr>
</xsl:template>

<xsl:template match="correction">
  <tr><td></td>
      <td><xsl:value-of select="attribute::index"/>
          <xsl:value-of select="."/></td>
  </tr>
</xsl:template>

</xsl:stylesheet>

出力結果は…実際に試してみてください。:-)

7. 最後に

こうしてもとのデータを XML にしておけば、XSLT スタイルシートを書くだけ で、様々なフォーマットの文書に変換できます。必要な情報だけを抜き出して CSV 形式で出力し、データベースに登録することもできます。(たぶん)
これらを行っている最中は試行錯誤の連続で、Word のままでよかったんじゃ ないかなどと思ったりもしましたが、一度仕組みを作ってしまえば、あとは もとになる XML 文書を書くだけですので、今後はずいぶん手間がはぶけるな と思いました。Word から脱却できたことが、実は一番嬉しかったことなのかも しれません。(^__^)

Powered by Apache PostgreSQL Usupi Logo Kuri Logo
[Home] [Kuri] [Sysad] [Internet?] [Blog] [Java] [Windows] [Download] [Profile] [Flash] [-]
usu@usupi.org Last modified : Wed Jun 6 14:37:44 2001