プログラミング言語XSLT
- 関数型言語
- チューリング完全
- 引数はすべてキーワード引数
- データ構造はすべて木構造(というかXML)
- 入力データに起動するプログラムを記述する必要がある*1
- C++のtemplateよりも遥かに冗長な構文
- DSL(XPath)の力を借りないとほとんど何も出来ない中途半端さ
では早速、Hello, world!を表示するありきたりな例から。
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version = "1.0"> <xsl:template match="/"> Hello, world! </xsl:template> </xsl:stylesheet>
これだけでは何も出来ないので、呼び出し側を作る必要がありますね。
その前に、上のファイルをhello.xslとして保存しといてください。
<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet type="text/xsl" href="hello.xsl"?> <main/>
これを適当な名前(hello.xmlとか)で保存して、ブラウザで開けば画面にHello, world!と表示されるはずです。
プログラミング言語XSLTでは、このように最低2つのファイルが必要となるわけですね。
なんて回りくどい言語なんでしょうか。同じようにブラウザさえあれば実行できるJavaScriptと比べて、全然お手軽さが無いです。
ちなみにJavaScriptで同じようなことをやろうと思ったら、アドレスバーに
javascript:document.write("Hello, world!");
と入力してEnterを押すだけです。お手軽ですね。
しかしXSLTプログラマはこんな事ではくじけません。
XSLTが関数型言語であることを示すために、foldl関数を実装して、それを使ってsum関数も実装してみましょう。
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version = "1.0"> <xsl:template name="foldl"> <xsl:param name="func"/> <xsl:param name="init"/> <xsl:param name="list"/> <xsl:if test="$list"> <xsl:variable name="result"> <xsl:apply-templates select="$func[1]"> <xsl:with-param name="arg0" select="$func[position() > 1]"/> <xsl:with-param name="arg1" select="$init"/> <xsl:with-param name="arg2" select="$list[1]"/> </xsl:apply-templates> </xsl:variable> <xsl:call-template name="foldl"> <xsl:with-param name="func" select="$func"/> <xsl:with-param name="init" select="$result"/> <xsl:with-param name="list" select="$list[position() > 1]"/> </xsl:call-template> </xsl:if> <xsl:if test="not($list)"> <xsl:copy-of select="$init"/> </xsl:if> </xsl:template> <xsl:template name="sum" xmlns:add="add"> <xsl:param name="list"/> <xsl:variable name="adder" select="document('')/*/add:*[1]"/> <xsl:call-template name="foldl"> <xsl:with-param name="func" select="$adder"/> <xsl:with-param name="list" select="$list"/> <xsl:with-param name="init" select="0"/> </xsl:call-template> </xsl:template> <xsl:template match="*[namespace-uri()='add']"> <xsl:param name="arg1"/> <xsl:param name="arg2"/> <xsl:value-of select="$arg1 + $arg2"/> </xsl:template> <add:add xmlns:add="add"/> <xsl:template match="/"> <xsl:call-template name="sum"> <xsl:with-param name="list" select="/items/*"/> </xsl:call-template> </xsl:template> </xsl:stylesheet>
・・・やはりこれだけでは何も出来ません。データを作る必要がありますね。
まずは上のファイルをtooverbose.xslとでも名前をつけて保存しておきましょう。
そして、以下の内容のファイルを適当な名前で作成してください。
<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet type="text/xsl" href="tooverbose.xsl"?> <items> <item>10</item> <item>5</item> <item>2</item> <item>3</item> <item>11</item> <item>6</item> <item>5</item> </items>
作ったXMLをブラウザで開くと結果が表示されるはず*2です。
さらに詳しいことはThe Functional Programming Language XSLT - A proof through examplesを読めば、あなたも明日からXSLTプログラマに!
一応、foldlとsumのJavaScriptによる実装例も置いておきますね。
function foldl(func, init, ary) { if (ary.length == 0) return init; return foldl(func, func(init, ary[0]), ary.slice(1, ary.length)); } function sum(ary) { return foldl(function(a, b) { return a + b; }, 0, ary); } document.write(sum([10, 5, 2, 3, 11, 6, 5]));
・・・XSLTのすばらしさが際立ちますね!