USの同僚から「お前のDITA-OTのプラグイン、DITA-OT1.8.5でやるとこけるで~!」と連絡がありました.私はずっと1.8.4を使っていたので気が付きませんでしたが、確かに1.8.5でやると一発でこけます.原因を調べてみると、1.8.5からはlq/@hrefの処理をDITA-OTが行うように変更されていました.1.8.4までは、ここに何を書こうがDITA-OTは何もやってくれなかったのです.(仕方がないので自前で処理していました)ところが1.8.5からは別の処理を付け加えねばなりません.ということはプラグインはDITA-OTのバージョンにより処理を分岐させる必要があります.でも1.8.4と1.8.5というようなバージョン表記だと大小比較は簡単な文字列比較ではできませんよね.という訳でDITA-OTのバージョンの比較用の関数を作ってみました.
<!--
function: Dispaly version compare result.
param: prmVersion1: Version 1
prmVersion2: Version 2
return: none
note:
-->
<xsl:function name="ahf:dispCompareOtVersion" as="xs:string">
<xsl:param name="prmVer1" as="xs:string"/>
<xsl:param name="prmVer2" as="xs:string"/>
<xsl:variable name="compareResult" as="xs:integer?" select="ahf:compareOtVersion($prmVer1,$prmVer2)"/>
<xsl:choose>
<xsl:when test="empty($compareResult)">
<xsl:sequence select="concat($prmVer1,' と ',$prmVer2,' は比較できません!')"/>
</xsl:when>
<xsl:when test="$compareResult eq 1">
<xsl:sequence select="concat($prmVer1,' gt ',$prmVer2)"/>
</xsl:when>
<xsl:when test="$compareResult eq -1">
<xsl:sequence select="concat($prmVer1,' lt ',$prmVer2)"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="concat($prmVer1,' eq ',$prmVer2)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<!--
function: Compare DITA-OT version.
param: prmVersion1: Version 1
prmVersion2: Version 2
return: xs:integer?
-1: Version 1 < Version 2
0: Version 1 = Version 2
1: Version 1 > Version 2
(): Error
note:
-->
<xsl:function name="ahf:compareOtVersion" as="xs:integer?">
<xsl:param name="prmVer1" as="xs:string"/>
<xsl:param name="prmVer2" as="xs:string"/>
<!-- バージョンを"."で区切ってxs:string*にする -->
<xsl:variable name="ver1Seq" as="xs:string*">
<xsl:analyze-string select="$prmVer1" regex="[\.]">
<xsl:matching-substring/>
<xsl:non-matching-substring>
<xsl:sequence select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:variable>
<xsl:variable name="ver2Seq" as="xs:string*">
<xsl:analyze-string select="$prmVer2" regex="[\.]">
<xsl:matching-substring/>
<xsl:non-matching-substring>
<xsl:sequence select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:variable>
<!--xs:string*を整数として扱って比較する-->
<xsl:sequence select="ahf:compareOtVersionNo($ver1Seq,$ver2Seq)"/>
</xsl:function>
<!--
function: Compare DITA-OT version No.
param: prmVersion1: Version 1
prmVersion2: Version 2
return: xs:integer?
-1: Version 1 < Version 2
0: Version 1 = Version 2
1: Version 1 > Version 2
(): Error
note:
-->
<xsl:function name="ahf:compareOtVersionNo" as="xs:integer?">
<xsl:param name="prmVer1" as="xs:string*"/>
<xsl:param name="prmVer2" as="xs:string*"/>
<xsl:choose>
<xsl:when test="exists($prmVer1[1]) and exists($prmVer2[1])">
<xsl:variable name="verNo1" as="xs:integer?" select="ahf:getOtVersionNo($prmVer1[1])"/>
<xsl:variable name="verNo2" as="xs:integer?" select="ahf:getOtVersionNo($prmVer2[1])"/>
<xsl:choose>
<!--両方とも整数値であれば整数で比較-->
<xsl:when test="exists($verNo1) and exists($verNo2)">
<xsl:choose>
<xsl:when test="$verNo1 gt $verNo2">
<xsl:sequence select="1"/>
</xsl:when>
<xsl:when test="$verNo1 lt $verNo2">
<xsl:sequence select="-1"/>
</xsl:when>
<xsl:otherwise>
<!--値が同じとき-->
<xsl:choose>
<xsl:when test="exists($prmVer1[position() gt 1]) or exists($prmVer2[position() gt 1])">
<!--いずれかが残りがあれば再帰的に比較-->
<xsl:sequence select="ahf:compareOtVersionNo($prmVer1[position() gt 1],$prmVer2[position() gt 1])"/>
</xsl:when>
<xsl:otherwise>
<!--残りがなければ値は等しい-->
<xsl:sequence select="0"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<!--整数として扱えなければ比較できない-->
<xsl:sequence select="()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<!-- 片方だけ残りがあればもう一方を"0"として比較する -->
<xsl:when test="exists($prmVer1[1]) and empty($prmVer2[1])">
<xsl:sequence select="ahf:compareOtVersion($prmVer1[1],'0')"/>
</xsl:when>
<xsl:when test="empty($prmVer1[1]) and exists($prmVer2[1])">
<xsl:sequence select="ahf:compareOtVersion('0',$prmVer2[1])"/>
</xsl:when>
<!-- 両方とも整数でなければ比較できない -->
<xsl:otherwise>
<xsl:sequence select="()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<!--
function: Get OT version number.
param: prmVersionNo
return: xs:integer?
note: DITA-OTのバージョン番号にはまれに"M2"などという文字列が入るので"M"は除外して比較するようにする.
整数にキャストできなければ空シーケンスを返す.
-->
<xsl:function name="ahf:getOtVersionNo" as="xs:integer?">
<xsl:param name="prmVerNo" as="xs:string"/>
<xsl:variable name="verNo" as="xs:string" select="replace($prmVerNo,'^M([0-9+])','$1')"/>
<xsl:choose>
<xsl:when test="$verNo castable as xs:integer">
<xsl:sequence select="xs:integer($verNo)"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
こうしておいて
<xsl:template match="/">
<xsl:message select="ahf:dispCompareOtVersion('1.8.5','1.8.5')"/>
<xsl:message select="ahf:dispCompareOtVersion('1.8.5.0','1.8.5')"/>
<xsl:message select="ahf:dispCompareOtVersion('1.8.5','1.8.4')"/>
<xsl:message select="ahf:dispCompareOtVersion('1.8.5','2.0')"/>
<xsl:message select="ahf:dispCompareOtVersion('1.8.5','1.8.M2')"/>
<xsl:message select="ahf:dispCompareOtVersion('1.8.2.0','1.8.M2')"/>
<xsl:message select="ahf:dispCompareOtVersion('1.8.5','1.8x.2x')"/>
</xsl:template>
で呼び出すとoXygenでは次のように表示されます.
[Saxon-PE] 1.8.5 eq 1.8.5
[Saxon-PE] 1.8.5.0 eq 1.8.5
[Saxon-PE] 1.8.5 gt 1.8.4
[Saxon-PE] 1.8.5 lt 2.0
[Saxon-PE] 1.8.5 gt 1.8.M2
[Saxon-PE] 1.8.2.0 eq 1.8.M2
[Saxon-PE] 1.8.5 と 1.8x.2x は比較できません!
この関数を使って無事に1.8.5とそれ未満のDITA-OTを識別して変換するコードを書くことができました.