今までxsl:templateのxsl:paramには必ず、@requiredと@asをつけるのを常としてきました.でもスタイルシートレベルのxsl:paramはあまりよくわかっていなかったのでこれらをつけることはありませんでした.この前EPUBを作るときに、antのbuild.xmlで次のような記述をしました.
(XSLTプロセッサはSaxonを使っているので、antのパラメータで、-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImplと指定しています.)
<xslt processor="trax"
in="${args.input}"
out="${temp.dir}${file.separator}dummy.xml"
style="${xmdf2epub.dir}${file.separator}xsl${file.separator}xmdf2epub_gen_xhtml.xsl"
force="true">
...
<param name="PRM_TOC_FILE" expression="${toc.file}" if="toc.file"/>
</xslt>
in="${args.input}"
out="${temp.dir}${file.separator}dummy.xml"
style="${xmdf2epub.dir}${file.separator}xsl${file.separator}xmdf2epub_gen_xhtml.xsl"
force="true">
...
<param name="PRM_TOC_FILE" expression="${toc.file}" if="toc.file"/>
</xslt>
<xsl:param name="PRM_TOC_FILE" as="xs:string" required="yes"/>
とやっていたら、antの起動パラメータで-Dtoc.fileを指定していなかったので、"[xslt] : Fatal Error! No value supplied for required parameter PRM_TOC_FILE"のエラーとなりました.さっそく次のように修正しました.
<xsl:param name="PRM_TOC_FILE" as="xs:string?" required="no" select="()"/>
今までスタイルシートのパラメータにはとんと無頓着だったのですが、@required属性は場合によっては有用です.パラメータが指定されたか指定されなかったかの判断がちゃんとできるのです.
パラメータが指定されているか否かの判定は、
<xsl:if test="exists($PRM_TOC_FILE)">
や
<xsl:if test="empty($PRM_TOC_FILE)">
のようにすれば、簡単にできます.
ちなみに
<xsl:param name="PRM_TOC_FILE" as="xs:string" required="no"/>
と書くとパラメータを与えなかったときは"Fatal Error! A value must be supplied for parameter $PRM_TOC_FILE because there is no default value for the required type"のエラーとなります.@asで型を指定してパラメータを与えない場合は初期値が必要なのです.
今後はスタイルシートレベルのxsl:paramも厳格にしてゆこうと思います.
ところで先日XSLT2.0のスタイルシートを見る機会がありましたが、xsl:templateレベルのxsl:paramで、@requiredも@asも指定していないものでした.C++やJavaなどの言語では当たり前のことなんですが、XSLT1.0の感覚の延長で書いているスタイルシートはどうもこういう書き方がまだ通用しているようです.これでもちゃんと作れば「動いちゃう」んですが、「なんとなく動いちゃう」場合もあります.例えば、
<xsl:param name="prmA">
だとrequired="no"とみなされ、xsl:apply-template、xsl:call-templateで呼び出すときに<xsl:with-param name="prmA" select="~"/>が指定していないと、XSLT2.0の仕様により、
If an optional parameter has no select attribute and has an empty sequence constructor, and if there is no as attribute, then the default value of the parameter is a zero length string.
になります.つまり""が初期値です.これが良いのかどうかは両論あると思います.私は否定派です.このような仕様を積極的に使用すべきではないと思います.よほどこの仕様を理解して使うのでない限り、それは単にプログラムのあいまいさを残すことになるだけだからです.プログラムのあいまいさはバグの温床になります.
このようなスタイルシートが出来てしまう原因として、まだ必ずしもXSLTがプログラムとして認めていられなくて、テキストエディタでスタイルシートを書く機会が多いからではないでしょうか?テキストエディタを使っている限り、このような風習から抜け出すことはできません.私はoXygenを使っているのでxsl:paramと打てばすぐに属性のname、as、requiredが候補としてメニューに出てきます.だからこれらを設定するのになんの負担もありません.でもテキストエディタでやっていたら、よっぽど根性がない限り、これらの属性を積極的に使うことはないでしょう.バシバシとタイプミスのないように属性を入力しなければならないからです.