XSLTスタイルシートから XSLTスタイルシートを作る!

一般的にXSLTスタイルシートはコツコツと手作りするものとずっと考えてきました.しかしある言語関係のテストをしなければならなくなり、さすがに一個一個手作りしていては間に合わなくなりました.というより、言語数が増えすぎて、とても手で作っていてはやっていられなくなったのです.

そこでXSLTスタイルシートを作り出すXSLTスタイルシートを考えてみました.ここで問題になるのは、xsl:のネームペースプリフィックスがついている(つまりネームスペースが、"http://www.w3.org/1999/XSL/Transform"である要素)はXSLTプロセッサが、自分が処理すべき要素として解釈するということです.これは当たり前なのですが、このスタイルシートを作り出すスタイルシートも同様にネームスペースが、"http://www.w3.org/1999/XSL/Transform"である要素の集合体であるということです.つまり、「自分で」「自分自身と似たもの」を作り出せなければなりません.

そこでXSLT 1.0から提供されているのが、

<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>

という宣言です.これは、XSLTスタイルシートの先頭で

<xsl:stylesheet version="2.0" 
    xmlns:axsl="file://namespace.alias"
    exclude-result-prefixes="xs xsl">
    
などとネームスペースプリフィックスaxslを暫定的に宣言しておき、xsl:namespace-aliasで指定したように、出力時にネームスペースプリフィックスを強制的に"axsl"から"xsl"に書き換えてくれます.これでバッチリXSLTスタイルシートを生成するXSLTスタイルシートを簡単に書くことができます.

例えばちょっと前後関係を省略していますが、次のような中国語簡体字用のXSLTスタイルシートから

        <xsl:result-document method="xml" version="1.0" indent="yes" encoding="UTF-8" href="{resolve-uri(concat('stylesheet/xslt',$pXsltVersion,'/dbtofo',$xsltVersionSuffix,'_',$xmlLang,'.xsl'),static-base-uri())}">
            <xsl:comment>DocBook to XSL-FO stylesheet for <xsl:value-of select="$xmlLang"/></xsl:comment>
            <axsl:stylesheet version="{$pXsltVersion}">
                <axsl:import href="{concat('common/dbtofo',$xsltVersionSuffix,'.xsl')}"/>
                <axsl:output method="xml" version="1.0" indent="no" encoding="UTF-8"/>
                <axsl:attribute-set name="atsRoot">
                    <axsl:attribute name="font-family">SimHei</axsl:attribute>
                </axsl:attribute-set>
                <axsl:variable name="cIndexTitle" select="'索引'"/>
                <axsl:variable name="cGroupTitleAlt" select="'记号,数字'"/>
            </axsl:stylesheet>
        </xsl:result-document>

次のようなXSLTスタイルシートを生成できます.

<?xml version="1.0" encoding="UTF-8"?>
<!--DocBook to XSL-FO stylesheet for zh-CN-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:import href="common/dbtofo2.xsl"/>
   <xsl:output method="xml" version="1.0" indent="no" encoding="UTF-8"/>
   <xsl:attribute-set name="atsRoot">
      <xsl:attribute name="font-family">SimHei</xsl:attribute>
   </xsl:attribute-set>
   <xsl:variable name="cIndexTitle" select="'索引'"/>
   <xsl:variable name="cGroupTitleAlt" select="'记号,数字'"/>
</xsl:stylesheet>

やってみるとわかりますが超便利です.今までは、言語毎にテストデータをXSLTスタイルシートで自動生成することはやっていましたが、今回それを処理するXSLTスタイルシートも自動で作れるようになりました.

ただしちょっと困ったのがantによる"繰り返し処理(ループ)"です.ループをするためには、例えば言語を表すプロパティを次々に変えてスタイルシートを作り出せねばなりません.でもご存知のようにantではプロパティはイミュータブルなのです.(書き換えることが出来ません)ですので元々のantには<for>に該当するものがないのです.これは次の機会に書きたいと思います.