他のスタイルシートをインポートして使う(2)

前に少し書きましたが、要素にマッチングするテンプレートで、インポートされる側にpriority="N"で優先順位をつけていても、インポートする側で一番低いpriorityのマッチングテンプレートをオーバーライドしてしまうと、話がやっかいになってしまいます.

以前に出した例は以下の様なものです.

[インポートされる側のスタイルシート
<xsl:template match="*[contains(@class,' topic/ph ')]">

<!-- b要素のテンプレート(斜体を処理)-->
<xsl:template match="*[contains(@class,' hi-d/b ')]" priority="2">

<!-- i要素のテンプレート(ボールドを処理)-->
<xsl:template match="*[contains(@class,' hi-d/i ')]" priority="2">

[インポートする側のテンプレート]
<xsl:template match="*[contains(@class,' topic/ph ')]">

こう書いてしまうと、b要素やi要素のテンプレートは「永遠に呼び出されることはなくなってしまう」ということです.

これは、b要素は

"+ topic/ph hi-d/b "

でi要素も同じく

"+ topic/ph hi-d/i "

そしてph要素は

"- topic/ph "

というクラス属性であり、インポートしているときはインポートする側のテンプレートが一番優先されて、まず" topic/ph "がマッチしてしまうからです.

ではどうするかなのですが、以前はb要素、i要素を処理するテンプレートもインポートする側に記述しなければならないと書きました.でもこんなのやっかいですね.もっといい方法があります.それはインポートされる側のテンプレートで、phのようなベースクラスのテンプレートの書き方をもっとうまくするのです.例えば以下のようになります.

[インポートされる側のスタイルシート
<xsl:template match="*[contains(@class,' topic/ph ')]">
  <xsl:call-template name="processPh"/>
</xsl:template>

<xsl:template name="processPh">
  ...ph要素を処理
</xsl:template>

[インポートする側のテンプレート]
<!--processPhをオーバーライドします-->
<xsl:template name="processPh">
  ...ph要素を処理
</xsl:template>

このようにベースクラスを直接処理せずにxsl:call-templateで処理しておけば、インポートされる側のマッチングpriorityの優先順位を乱すことなく目的の処理をインポートする側のテンプレートで実現できるでしょう.

DITAではこのようなベースのクラスを持った要素はあるのですが、数はそう多くはありません.例えばmapではtopicref、topicではph,keyword,dataなどが該当します.通常これらのテンプレートをオーバーライドすることはそうはないのですが、それでもお客様によっては要望により、そのような処理が必要になることが多々あります.ちょっとした工夫ですが覚えておいて損はないと思います.