DITA1.2から追加されたtask/stepsの要素にstepsectionというのがあります.stepとstepの間に入れるちょっとした解説のような位置づけでしょうか?これはstrict taskでもgeneral taskでも同様です.で、気になったのはHTML出力です.このstepsectionはクラスが"- topic/li task/stepsection"で要するにliなのです.HTMLでtask/stepsをolに変換していると思うのですが、このstepsectionが出てくると大変困ります.何故ってN.というリスト番号をつけてはいけないのですから...で、DITA-OT1.5.3のHTML出力を見るとちゃんとうまく回避していました.
<ol>
<li>stepの内容</li>
<li>stepの内容</li>
<ol>
<p>stepsectionの内容</p>
<ol start="3">
<li>stepの内容</li>
<li>stepの内容</li>
<ol>
<li>stepの内容</li>
<li>stepの内容</li>
<ol>
<p>stepsectionの内容</p>
<ol start="3">
<li>stepの内容</li>
<li>stepの内容</li>
<ol>
というふうにolをstepsectionの前後で分割出力していました.さすがにやりますなと思って実際のスタイルシートを見たのですが([DITA-OT]/xsl/xslhtml/taskdisplay.xsl)、ちらっと見ただけでイヤになってしまいました.あいかわらずXSL1.0のままで正直なところ「スパゲティの塊」にしか見えません.やはりもう10年近くも引き継いできたスタイルシートをそう簡単にXSLT2.0には移行できないのでしょう.modeとxsl:paramでグチャグチャのスタイルシートを見て、これはとてもreference implementationにはならないなと思いました.
文句ばかり言っていられないので、XSLT2.0ならどう書くか?試しに作ってみました.以下がコードです.少し複雑ですが、XSLT1.0で書くよりずっと「思ったとおり」にかけます.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xsl:import href="元のHTML出力のスタイルシート"/>
<xsl:template match="*[contains(@class,' task/steps ')]">
<xsl:call-template name="processStep">
<xsl:with-param name="prmStep" select="child::*[1]"/>
<xsl:with-param name="prmOlStart" select="1"/>
</xsl:call-template>
</xsl:template>
<xsl:call-template name="processStep">
<xsl:with-param name="prmStep" select="child::*[1]"/>
<xsl:with-param name="prmOlStart" select="1"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="processStep">
<xsl:param name="prmStep" as="element()?" required="yes"/>
<xsl:param name="prmOlStart" as="xs:integer" required="yes"/>
<xsl:choose>
<!-- 先頭がstep -->
<xsl:when test="$prmStep[contains(@class,' task/step ')]">
<!-- stepの次のグループの先頭を求める
stepsectionがあればそれ、なければempty
-->
<xsl:variable name="next"
select="if ($prmStep/following-sibling::*[contains(@class,' task/stepsection ')])
then $prmStep/following-sibling::*[contains(@class,' task/stepsection ')][1]
else ()" as="element()?"/>
<!-- 処理すべきstepを求める
次のグループの先頭があれば、そこまでのstep
なければ以降のstep全部
-->
<xsl:variable name="step"
select="if (empty($next))
then $prmStep | $prmStep/following-sibling::*[contains(@class,' task/step ')]
else $prmStep | $prmStep/following-sibling::*[contains(@class,' task/step ')][. << $next ]"
as="element()+"/>
<!-- 処理すべきstepからolを生成 -->
<ol start="{$prmOlStart}">
<xsl:apply-templates select="$step"/>
</ol>
<!-- 次のolの開始番号を求める -->
<xsl:variable name="nextOlStart" select="$prmOlStart + count($step)"/>
<!-- 次があれば自分自身を呼び出す -->
<xsl:if test="exists($next)">
<xsl:call-template name="processStep">
<xsl:with-param name="prmStep" select="$next"/>
<xsl:with-param name="prmOlStart" select="$nextOlStart"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<!-- 先頭がstepsection -->
<xsl:when test="$prmStep[contains(@class,' task/stepsection ')]">
<!-- stepsectionの次のグループの先頭を求める
stepがあればそれ、なければempty
-->
<xsl:variable name="next"
select="if ($prmStep/following-sibling::*[contains(@class,' task/step ')])
then $prmStep/following-sibling::*[contains(@class,' task/step ')][1]
else ()" as="element()?"/>
<!-- 処理すべきstepsectionを求める
次のグループの先頭があれば、そこまでのstepsection
なければ以降のstepsection全部
-->
<xsl:variable name="stepSection"
select="if (empty($next))
then $prmStep | $prmStep/following-sibling::*[contains(@class,' task/stepsection ')]
else $prmStep | $prmStep/following-sibling::*[contains(@class,' task/stepsection ')][. << $next ]"
as="element()+"/>
<!-- 処理すべきstepsectionを処理 -->
<xsl:for-each select="$stepSection">
<xsl:apply-templates select="."/>
</xsl:for-each>
<!-- 次があれば自分自身を呼び出す -->
<xsl:if test="exists($next)">
<xsl:call-template name="processStep">
<xsl:with-param name="prmStep" select="$next"/>
<xsl:with-param name="prmOlStart" select="$prmOlStart"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:param name="prmStep" as="element()?" required="yes"/>
<xsl:param name="prmOlStart" as="xs:integer" required="yes"/>
<xsl:choose>
<!-- 先頭がstep -->
<xsl:when test="$prmStep[contains(@class,' task/step ')]">
<!-- stepの次のグループの先頭を求める
stepsectionがあればそれ、なければempty
-->
<xsl:variable name="next"
select="if ($prmStep/following-sibling::*[contains(@class,' task/stepsection ')])
then $prmStep/following-sibling::*[contains(@class,' task/stepsection ')][1]
else ()" as="element()?"/>
<!-- 処理すべきstepを求める
次のグループの先頭があれば、そこまでのstep
なければ以降のstep全部
-->
<xsl:variable name="step"
select="if (empty($next))
then $prmStep | $prmStep/following-sibling::*[contains(@class,' task/step ')]
else $prmStep | $prmStep/following-sibling::*[contains(@class,' task/step ')][. << $next ]"
as="element()+"/>
<!-- 処理すべきstepからolを生成 -->
<ol start="{$prmOlStart}">
<xsl:apply-templates select="$step"/>
</ol>
<!-- 次のolの開始番号を求める -->
<xsl:variable name="nextOlStart" select="$prmOlStart + count($step)"/>
<!-- 次があれば自分自身を呼び出す -->
<xsl:if test="exists($next)">
<xsl:call-template name="processStep">
<xsl:with-param name="prmStep" select="$next"/>
<xsl:with-param name="prmOlStart" select="$nextOlStart"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<!-- 先頭がstepsection -->
<xsl:when test="$prmStep[contains(@class,' task/stepsection ')]">
<!-- stepsectionの次のグループの先頭を求める
stepがあればそれ、なければempty
-->
<xsl:variable name="next"
select="if ($prmStep/following-sibling::*[contains(@class,' task/step ')])
then $prmStep/following-sibling::*[contains(@class,' task/step ')][1]
else ()" as="element()?"/>
<!-- 処理すべきstepsectionを求める
次のグループの先頭があれば、そこまでのstepsection
なければ以降のstepsection全部
-->
<xsl:variable name="stepSection"
select="if (empty($next))
then $prmStep | $prmStep/following-sibling::*[contains(@class,' task/stepsection ')]
else $prmStep | $prmStep/following-sibling::*[contains(@class,' task/stepsection ')][. << $next ]"
as="element()+"/>
<!-- 処理すべきstepsectionを処理 -->
<xsl:for-each select="$stepSection">
<xsl:apply-templates select="."/>
</xsl:for-each>
<!-- 次があれば自分自身を呼び出す -->
<xsl:if test="exists($next)">
<xsl:call-template name="processStep">
<xsl:with-param name="prmStep" select="$next"/>
<xsl:with-param name="prmOlStart" select="$prmOlStart"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- stepとstepsectionのテンプレートは字数制限で省略-->
</xsl:stylesheet>
やはりプログラミング言語は思ったストリー通りにかけないとダメですね.XSLT1.0で歯を食いしばって書いてもメンテナンス性が悪くなるだけです.上記のスタイルシートで出力したHTMLの画面はこんな感じになります.