XSLTでDocBookを複数のreStructuredTextに分割してtoctreeを作る
こういう感じのDocBookがあるとする
code: xml
<book>
<preface id="preface_id">...</preface>
<part id="part1_id">...</part>
<part id="part2_id">...</part>
</book>
やりたいこと
book
目次がいる
ファイル名:index.rst
preface, part
それぞれidに応じた名前でファイル分割
preface_id.rst
part1_id.rst
part2_id.rst
つまり、以下のようなindex.rstが出力としてほしい
code: index.rst
.. toctree::
./preface_id.rst
./part1_id.rst
./part2_id.rst
xsltは以下のようになる
code: convert.rst
<xsl:template match="/book">
<!-- 親要素のファイルを作成 -->
<xsl:document href="output/index.rst">
<!-- 目次を作る -->
<xsl:text>.. toctree:: </xsl:text>
<xsl:text> </xsl:text>
<xsl:apply-templates select="preface" mode="toc-node" />
<xsl:apply-templates select="part" mode="toc-node" />
</xsl:document>
<!-- 子要素毎にファイルを作る -->
<xsl:apply-templates select="preface" mode="main" />
<xsl:apply-templates select="part" mode="main" />
</xsl:template>
<xsl:template match="preface" mode="toc-node">
<xsl:value-of select="@id" />
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template match="preface" mode="main" >
<xsl:variable name="fileName" select="concat('output/', @id, '.rst')" />
<xsl:document href="{$fileName}">
<xsl:apply-templates select="*" />
</xsl:document>
</xsl:template>
<!-- 以下、partもprefaceと同様 -->
解説
book(親要素)からpreface, part(子要素)の属性や値にアクセスしない
for-eachを使って子要素のidを拾ってきたりできるけど、DocBookが巨大だと処理時間が著しく増えるので微妙
親要素からmodeを使って子要素をセレクトし、それ以上のことは子要素側に任せる
子要素のmode="toc-node"は親要素のテンプレートから目次作成用に呼び出される
親要素のテンプレートの<xsl:document>内で呼び出されている
<xsl:value-of>は親要素側で指定したファイル(index.rst)に書き込まれる
mode="main"は子要素自身の処理をする
同じようにファイルを作って、目次を作って……
複数ファイルが入れ子になっている場合は、こういう組み合わせのテンプレートを大量に作ることになる