DOM(Document Object Model)やSAX(Simple API for XML)を使ったプログラムを書くのも良いけれど、XML文書の構造を変換するのならXLST(XSL Transformations)を利用した方が開発効率は遥かに高いです。 プログラミング言語の知識も必要ないですしね。 (・∀・)ベンリ!!
入力するXMLファイル
それでは試しに先日DOMとSAXで作ったプログラムと同じ結果を出力するXSLTスタイルシートを書いてみましょう。 ソースXML文書はGundamList.xmlを使います。
<?xml version="1.0" encoding="Shift_JIS" ?>
<!DOCTYPE gundamList SYSTEM "GundamList.dtd">
<gundamList xmlns="urn:gundam:anime">
<gundam media="TV">
<name>機動戦士ガンダム</name>
<calendar jpn="宇宙世紀" eng="U.C.">0079</calendar>
<director>富野由悠季</director>
</gundam>
<gundam media="TV">
<name>機動戦士Zガンダム</name>
<calendar jpn="宇宙世紀" eng="U.C.">0087</calendar>
<director>富野由悠季</director>
</gundam>
<gundam media="TV">
<name>機動戦士ガンダムZZ</name>
<calendar jpn="宇宙世紀" eng="U.C.">0088</calendar>
<director>富野由悠季</director>
</gundam>
<gundam media="MOVIE">
<name>機動戦士ガンダム 逆襲のシャア</name>
<calendar jpn="宇宙世紀" eng="U.C.">0093</calendar>
<director>富野由悠季</director>
</gundam>
<gundam media="OVA">
<name>機動戦士ガンダム0080 ポケットの中の戦争</name>
<calendar jpn="宇宙世紀" eng="U.C.">0080</calendar>
<director>高山文彦</director>
</gundam>
<gundam media="MOVIE">
<name>機動戦士ガンダムF91</name>
<calendar jpn="宇宙世紀" eng="U.C.">0123</calendar>
<director>富野由悠季</director>
</gundam>
<gundam media="OVA">
<name>機動戦士ガンダム0083 STARDUST MEMORY</name>
<calendar jpn="宇宙世紀" eng="U.C.">0083</calendar>
<director>加瀬充子</director>
<director>今西隆志</director>
</gundam>
<gundam media="TV">
<name>機動戦士Vガンダム</name>
<calendar jpn="宇宙世紀" eng="U.C.">0153</calendar>
<director>富野由悠季</director>
</gundam>
<gundam media="TV">
<name>機動武闘伝Gガンダム</name>
<calendar jpn="未来世紀" eng="F.C.">60</calendar>
<director>今川泰宏</director>
</gundam>
<gundam media="TV">
<name>新機動戦記ガンダムW</name>
<calendar jpn="アフターコロニー" eng="A.C.">195</calendar>
<director>池田成</director>
<director>高松信司</director>
</gundam>
<gundam media="TV">
<name>新機動戦記ガンダムX</name>
<calendar jpn="アフターウォー" eng="A.W.">15</calendar>
<director>高松信司</director>
</gundam>
<gundam media="OVA">
<name>機動戦士ガンダム 第08MS小隊</name>
<calendar jpn="宇宙世紀" eng="U.C.">0079</calendar>
<director>神田武幸</director>
<director>飯田馬之介</director>
</gundam>
<gundam media="OVA">
<name>新機動戦記ガンダムW Endless Waltz</name>
<calendar jpn="アフターコロニー" eng="A.C.">196</calendar>
<director>青木康直</director>
</gundam>
<gundam media="OVA">
<name>機動戦士ガンダム 第08MS小隊 特別編 ラスト・リゾート</name>
<calendar jpn="宇宙世紀" eng="U.C.">0079</calendar>
<director>森邦宏</director>
<director>仕舞屋鉄</director>
</gundam>
<gundam media="TV">
<name>∀ガンダム</name>
<calendar jpn="正暦" eng="C.C.">2345</calendar>
<director>富野由悠季</director>
</gundam>
<gundam media="TV">
<name>機動戦士ガンダムSEED</name>
<calendar jpn="コズミック・イラ" eng="C.E.">71</calendar>
<director>福田己津央</director>
</gundam>
<gundam media="TV">
<name>機動戦士ガンダムSEED DESTINY</name>
<calendar jpn="コズミック・イラ" eng="C.E.">73</calendar>
<director>福田己津央</director>
</gundam>
<gundam media="OVA">
<name>機動戦士ガンダムSEED C.E.73 STARGAZER</name>
<calendar jpn="コズミック・イラ" eng="C.E.">73</calendar>
<director>西澤晋</director>
</gundam>
<gundam media="TV">
<name>機動戦士ガンダム00 ファーストシーズン</name>
<calendar jpn="西暦" eng="A.D.">2307</calendar>
<director>水島精二</director>
</gundam>
<gundam media="TV">
<name>機動戦士ガンダム00 セカンドシーズン</name>
<calendar jpn="西暦" eng="A.D.">2312</calendar>
<director>水島精二</director>
</gundam>
</gundamList>
XSLTスタイルシートの課題1
まずは「GundamList.xmlの中から富野由悠季監督のガンダム作品を抽出する」XSLTスタイルシートで、次のような出力結果を目指します。
U.C.0079 機動戦士ガンダム U.C.0087 機動戦士Zガンダム U.C.0088 機動戦士ガンダムZZ U.C.0093 機動戦士ガンダム 逆襲のシャア U.C.0123 機動戦士ガンダムF91 U.C.0153 機動戦士Vガンダム C.C.2345 ∀ガンダム 以上、7作品
色々な書き方で実現できるのですけど、今回はXMLマスター:プロフェッショナル試験に出題されるxsl:key
関数を使用してみます。
XSLTスタイルシート(GundamSax.xsl)は次のようになりました。
文字列比較だらけになってしまうJavaやC#のコードよりスッキリしてますよね。
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ani="urn:gundam:anime">
<xsl:key name="director" match="ani:gundamList/ani:gundam" use="ani:director" />
<xsl:variable name="kantoku" select="'富野由悠季'" />
<xsl:output method="text" />
<xsl:template match="/">
<xsl:apply-templates select="key('director', $kantoku)" />
<xsl:text>以上、</xsl:text>
<xsl:value-of select="count(key('director', $kantoku))" />
<xsl:text>作品</xsl:text>
</xsl:template>
<xsl:template match="ani:gundam">
<xsl:value-of select="ani:calendar/@eng" />
<xsl:value-of select="ani:calendar" />
<xsl:text> </xsl:text>
<xsl:value-of select="ani:name" />
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
XSLTスタイルシートの課題2
続いて「GundamList.xmlの中から宇宙世紀(U.C.)のガンダムシリーズを抜き出して、作中の年表順にソートする」XSLTスタイルシートで、次のような出力結果を目指します。
U.C.0079 機動戦士ガンダム U.C.0079 機動戦士ガンダム 第08MS小隊 U.C.0079 機動戦士ガンダム 第08MS小隊 特別編 ラスト・リゾート U.C.0080 機動戦士ガンダム0080 ポケットの中の戦争 U.C.0083 機動戦士ガンダム0083 STARDUST MEMORY U.C.0087 機動戦士Zガンダム U.C.0088 機動戦士ガンダムZZ U.C.0093 機動戦士ガンダム 逆襲のシャア U.C.0123 機動戦士ガンダムF91 U.C.0153 機動戦士Vガンダム 以上、10作品
これはxsl:key
関数で抽出した結果にxsl:sort
を適用するだけでできます。
XSLTスタイルシート(GundamDom.xsl)は次のようになりました。
ソート処理が組み込まれていると楽チンなことこの上ない。
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ani="urn:gundam:anime">
<xsl:key name="century" match="ani:gundamList/ani:gundam" use="ani:calendar/@eng" />
<xsl:variable name="eng" select="'U.C.'" />
<xsl:output method="text" />
<xsl:template match="/">
<xsl:apply-templates select="key('century', $eng)">
<xsl:sort select="ani:calendar" data-type="number" />
</xsl:apply-templates>
<xsl:text>以上、</xsl:text>
<xsl:value-of select="count(key('century', $eng))" />
<xsl:text>作品</xsl:text>
</xsl:template>
<xsl:template match="ani:gundam">
<xsl:value-of select="ani:calendar/@eng" />
<xsl:value-of select="ani:calendar" />
<xsl:text> </xsl:text>
<xsl:value-of select="ani:name" />
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
JavaでXSLTスタイルシートを処理する
XSLTスタイルシートが用意できたらXLSTプロセッサに処理してもらいます。 JavaとC#にはXSLTを処理するクラスが用意されてるので使ってみましょう。 Javaのコード(GundamXslt.java)は次のようになります。
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
public class GundamXslt
{
public static void main(String[] args)
{
try
{
// XSLファイルを読み込む
StreamSource tplXsl = new StreamSource("GundamDom.xsl");
TransformerFactory trf = TransformerFactory.newInstance();
Transformer xslt = trf.newTransformer(tplXsl);
// XMLファイルをXSLTで変換して出力
StreamSource srcXml = new StreamSource("GundamList.xml");
xslt.setOutputProperty("encoding", "Shift_JIS");
xslt.transform(srcXml, new StreamResult(System.out));
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
C#でXSLTスタイルシートを処理する
C#のコード(GundamXslt.cs)は次のようになります。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
namespace GundamXslt
{
class GundamXslt
{
static void Main(string[] args)
{
// XSLファイルを読み込む
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(@"..\..\GundamSax.xsl");
// XMLファイルをXSLTで変換して出力
XPathDocument doc = new XPathDocument(@"..\..\GundamList.xml");
XsltArgumentList argList = new XsltArgumentList();
xslt.Transform(doc, argList, Console.Out);
}
}
}
とりあえずXLSTで実装しておいて、もし速度が必要なら後でDOMやSAXで書き直す開発スタイルが良さそうですね。 ( ゚Д゚)y─┛~~
0 件のコメント: