您如何获得 DocBook XSL 的分块来为每个页面生成完整的 TOC?
How do you get DocBook XSL's chunking to generate a full TOC for each page?
我有一堆 DocBook XML 文件,所有这些文件都合并到一个 DocBook 文件中以转换为 HTML。每个单独的文档都是一个参考页(用于功能或类似结构)。我使用分块 HTML 生成,这样每个参考页都成为它自己的 HTML 页。
问题是这样的:我希望每个页面上有 table 个内容。但是我不要the table of contents for that page。我想要整个参考手册的完整目录。
也就是说,我希望能够使用目录从任何页面跳转到任何其他页面。我可以使用 CSS 样式将目录粘贴在左侧(甚至隐藏它以便移动查看或其他)。
有一种显而易见的方法可以解决这个问题。我可以通过 post-process 脚本提取主目录,然后让脚本将其复制到每个输出 HTML 文档中。我正在寻找一种在 DocBook XSL 中工作的方法。
我希望结果看起来更像 DocBook XSL's newer webhelp,但不那么明显 JavaScript 参与。
有一种相对简单的方法可以做到这一点,但我很确定你不能不 creating a DocBook XSL customization layer 或直接修改已安装的(系统)样式表。
无论如何,我认为您需要修改或覆盖的实际 docbook-xsl 模板名为 make.toc
,位于文件 html/autotoc.xsl
.
的样式表分布中
这是一个很大的模板——将近一百行——但你只需要对其进行一行更改:
--- /usr/share/xml/docbook/stylesheet/docbook-xsl/html/autotoc.xsl 2012-12-16 11:35:12.000000000 +0900
+++ /opt/workspace/autotoc.xsl 2015-12-26 09:19:36.000000000 +0900
@@ -28,7 +28,7 @@
</xsl:variable>
<xsl:template name="make.toc">
- <xsl:param name="toc-context" select="."/>
+ <xsl:param name="toc-context" select="/"/>
<xsl:param name="toc.title.p" select="true()"/>
<xsl:param name="nodes" select="/NOT-AN-ELEMENT"/>
也就是说,您需要调用该模板并将 toc-context
参数设置为“/
”(而不是“.
”)。
默认的“.
”值告诉模板,在为块创建 TOC 时,它应该只查看当前正在处理的任何元素的(子)内容(即根那个特定的块);例如,如果它正在处理 section
,它只会查看 section
.
的子项
但是,如果您将该值更改为“/
”,您就是在告诉模板每次(重新)查看源文档的全部内容。因此,如果您的文档是 book
,它每次都会为您提供整本书的完整目录,或者如果您的文档是 article
,整篇文章等
所以我认为这应该能满足您的需求。
如果您决定只修改已安装的样式表,并且您已经从您使用的任何 OS 特定的包管理器安装了它们,您需要找到 html/autotoc.xsl
文件的安装位置。
在我的 Debian Linux 系统上,html/autotoc.xsl
文件在这里:
/usr/share/xml/docbook/stylesheet/docbook-xsl/html/autotoc.xsl
在我的 OS X 系统上,它是从自制程序包安装的,它在这里:
/usr/local/opt/docbook-xsl/docbook-xsl/html/autotoc.xsl
如果您决定改为 create a customization layer,则需要将整个 make.toc
模板复制到您的自定义层(但 toc-context
参数更改为“/
").
截至 2019-07-06 docbook-xsl-1.79.2,当前接受的答案不足以使每个 table 的内容完整。
但是,以下 XSL 模板可以。关键的见解是单步执行 Oxygen XML 编辑器的调试器,并注意到虽然 toc-context
已正确设置为根元素,但 nodes
变量仍然是局部子集。
我撤消了 toc-context
更改。相反,我创建了一个新变量 root-nodes
选择 /
,并编辑了 make.toc
模板以使用 root-nodes
而不是 nodes.
现在将其放入我的自定义层会使每个 table 内容成为完整的 table 内容。
<xsl:template name="make.toc">
<xsl:param name="toc-context" select="."/>
<xsl:param name="toc.title.p" select="true()"/>
<xsl:param name="nodes" select="/NOT-AN-ELEMENT"/>
<xsl:variable name="root-nodes" select="/"/>
<xsl:variable name="nodes.plus" select="$root-nodes | d:qandaset"/>
<xsl:variable name="toc.title">
<xsl:if test="$toc.title.p">
<xsl:choose>
<xsl:when test="$make.clean.html != 0">
<div class="toc-title">
<xsl:call-template name="gentext">
<xsl:with-param name="key">TableofContents</xsl:with-param>
</xsl:call-template>
</div>
</xsl:when>
<xsl:otherwise>
<p>
<strong>
<xsl:call-template name="gentext">
<xsl:with-param name="key">TableofContents</xsl:with-param>
</xsl:call-template>
</strong>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:variable>
<xsl:choose>
<xsl:when test="$manual.toc != ''">
<xsl:variable name="id">
<xsl:call-template name="object.id"/>
</xsl:variable>
<xsl:variable name="toc" select="document($manual.toc, .)"/>
<xsl:variable name="tocentry" select="$toc//d:tocentry[@linkend=$id]"/>
<xsl:if test="$tocentry and $tocentry/*">
<div class="toc">
<xsl:copy-of select="$toc.title"/>
<xsl:element name="{$toc.list.type}" namespace="http://www.w3.org/1999/xhtml">
<xsl:call-template name="toc.list.attributes">
<xsl:with-param name="toc-context" select="$toc-context"/>
<xsl:with-param name="toc.title.p" select="$toc.title.p"/>
<xsl:with-param name="nodes" select="$root-nodes"/>
</xsl:call-template>
<xsl:call-template name="manual-toc">
<xsl:with-param name="tocentry" select="$tocentry/*[1]"/>
</xsl:call-template>
</xsl:element>
</div>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$qanda.in.toc != 0">
<xsl:if test="$nodes.plus">
<div class="toc">
<xsl:copy-of select="$toc.title"/>
<xsl:element name="{$toc.list.type}" namespace="http://www.w3.org/1999/xhtml">
<xsl:call-template name="toc.list.attributes">
<xsl:with-param name="toc-context" select="$toc-context"/>
<xsl:with-param name="toc.title.p" select="$toc.title.p"/>
<xsl:with-param name="nodes" select="$root-nodes"/>
</xsl:call-template>
<xsl:apply-templates select="$nodes.plus" mode="toc">
<xsl:with-param name="toc-context" select="$toc-context"/>
</xsl:apply-templates>
</xsl:element>
</div>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$root-nodes">
<div class="toc">
<xsl:copy-of select="$toc.title"/>
<xsl:element name="{$toc.list.type}" namespace="http://www.w3.org/1999/xhtml">
<xsl:call-template name="toc.list.attributes">
<xsl:with-param name="toc-context" select="$toc-context"/>
<xsl:with-param name="toc.title.p" select="$toc.title.p"/>
<xsl:with-param name="nodes" select="$root-nodes"/>
</xsl:call-template>
<xsl:apply-templates select="$root-nodes" mode="toc">
<xsl:with-param name="toc-context" select="$toc-context"/>
</xsl:apply-templates>
</xsl:element>
</div>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
注意:还有一个问题,即并非每个分块页面都有自己的目录,但这与此具体无关。如果我对它进行排序,我会添加评论说明我是如何做到的。
我有一堆 DocBook XML 文件,所有这些文件都合并到一个 DocBook 文件中以转换为 HTML。每个单独的文档都是一个参考页(用于功能或类似结构)。我使用分块 HTML 生成,这样每个参考页都成为它自己的 HTML 页。
问题是这样的:我希望每个页面上有 table 个内容。但是我不要the table of contents for that page。我想要整个参考手册的完整目录。
也就是说,我希望能够使用目录从任何页面跳转到任何其他页面。我可以使用 CSS 样式将目录粘贴在左侧(甚至隐藏它以便移动查看或其他)。
有一种显而易见的方法可以解决这个问题。我可以通过 post-process 脚本提取主目录,然后让脚本将其复制到每个输出 HTML 文档中。我正在寻找一种在 DocBook XSL 中工作的方法。
我希望结果看起来更像 DocBook XSL's newer webhelp,但不那么明显 JavaScript 参与。
有一种相对简单的方法可以做到这一点,但我很确定你不能不 creating a DocBook XSL customization layer 或直接修改已安装的(系统)样式表。
无论如何,我认为您需要修改或覆盖的实际 docbook-xsl 模板名为 make.toc
,位于文件 html/autotoc.xsl
.
这是一个很大的模板——将近一百行——但你只需要对其进行一行更改:
--- /usr/share/xml/docbook/stylesheet/docbook-xsl/html/autotoc.xsl 2012-12-16 11:35:12.000000000 +0900
+++ /opt/workspace/autotoc.xsl 2015-12-26 09:19:36.000000000 +0900
@@ -28,7 +28,7 @@
</xsl:variable>
<xsl:template name="make.toc">
- <xsl:param name="toc-context" select="."/>
+ <xsl:param name="toc-context" select="/"/>
<xsl:param name="toc.title.p" select="true()"/>
<xsl:param name="nodes" select="/NOT-AN-ELEMENT"/>
也就是说,您需要调用该模板并将 toc-context
参数设置为“/
”(而不是“.
”)。
默认的“.
”值告诉模板,在为块创建 TOC 时,它应该只查看当前正在处理的任何元素的(子)内容(即根那个特定的块);例如,如果它正在处理 section
,它只会查看 section
.
但是,如果您将该值更改为“/
”,您就是在告诉模板每次(重新)查看源文档的全部内容。因此,如果您的文档是 book
,它每次都会为您提供整本书的完整目录,或者如果您的文档是 article
,整篇文章等
所以我认为这应该能满足您的需求。
如果您决定只修改已安装的样式表,并且您已经从您使用的任何 OS 特定的包管理器安装了它们,您需要找到 html/autotoc.xsl
文件的安装位置。
在我的 Debian Linux 系统上,html/autotoc.xsl
文件在这里:
/usr/share/xml/docbook/stylesheet/docbook-xsl/html/autotoc.xsl
在我的 OS X 系统上,它是从自制程序包安装的,它在这里:
/usr/local/opt/docbook-xsl/docbook-xsl/html/autotoc.xsl
如果您决定改为 create a customization layer,则需要将整个 make.toc
模板复制到您的自定义层(但 toc-context
参数更改为“/
").
截至 2019-07-06 docbook-xsl-1.79.2,当前接受的答案不足以使每个 table 的内容完整。
但是,以下 XSL 模板可以。关键的见解是单步执行 Oxygen XML 编辑器的调试器,并注意到虽然 toc-context
已正确设置为根元素,但 nodes
变量仍然是局部子集。
我撤消了 toc-context
更改。相反,我创建了一个新变量 root-nodes
选择 /
,并编辑了 make.toc
模板以使用 root-nodes
而不是 nodes.
现在将其放入我的自定义层会使每个 table 内容成为完整的 table 内容。
<xsl:template name="make.toc">
<xsl:param name="toc-context" select="."/>
<xsl:param name="toc.title.p" select="true()"/>
<xsl:param name="nodes" select="/NOT-AN-ELEMENT"/>
<xsl:variable name="root-nodes" select="/"/>
<xsl:variable name="nodes.plus" select="$root-nodes | d:qandaset"/>
<xsl:variable name="toc.title">
<xsl:if test="$toc.title.p">
<xsl:choose>
<xsl:when test="$make.clean.html != 0">
<div class="toc-title">
<xsl:call-template name="gentext">
<xsl:with-param name="key">TableofContents</xsl:with-param>
</xsl:call-template>
</div>
</xsl:when>
<xsl:otherwise>
<p>
<strong>
<xsl:call-template name="gentext">
<xsl:with-param name="key">TableofContents</xsl:with-param>
</xsl:call-template>
</strong>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:variable>
<xsl:choose>
<xsl:when test="$manual.toc != ''">
<xsl:variable name="id">
<xsl:call-template name="object.id"/>
</xsl:variable>
<xsl:variable name="toc" select="document($manual.toc, .)"/>
<xsl:variable name="tocentry" select="$toc//d:tocentry[@linkend=$id]"/>
<xsl:if test="$tocentry and $tocentry/*">
<div class="toc">
<xsl:copy-of select="$toc.title"/>
<xsl:element name="{$toc.list.type}" namespace="http://www.w3.org/1999/xhtml">
<xsl:call-template name="toc.list.attributes">
<xsl:with-param name="toc-context" select="$toc-context"/>
<xsl:with-param name="toc.title.p" select="$toc.title.p"/>
<xsl:with-param name="nodes" select="$root-nodes"/>
</xsl:call-template>
<xsl:call-template name="manual-toc">
<xsl:with-param name="tocentry" select="$tocentry/*[1]"/>
</xsl:call-template>
</xsl:element>
</div>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$qanda.in.toc != 0">
<xsl:if test="$nodes.plus">
<div class="toc">
<xsl:copy-of select="$toc.title"/>
<xsl:element name="{$toc.list.type}" namespace="http://www.w3.org/1999/xhtml">
<xsl:call-template name="toc.list.attributes">
<xsl:with-param name="toc-context" select="$toc-context"/>
<xsl:with-param name="toc.title.p" select="$toc.title.p"/>
<xsl:with-param name="nodes" select="$root-nodes"/>
</xsl:call-template>
<xsl:apply-templates select="$nodes.plus" mode="toc">
<xsl:with-param name="toc-context" select="$toc-context"/>
</xsl:apply-templates>
</xsl:element>
</div>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$root-nodes">
<div class="toc">
<xsl:copy-of select="$toc.title"/>
<xsl:element name="{$toc.list.type}" namespace="http://www.w3.org/1999/xhtml">
<xsl:call-template name="toc.list.attributes">
<xsl:with-param name="toc-context" select="$toc-context"/>
<xsl:with-param name="toc.title.p" select="$toc.title.p"/>
<xsl:with-param name="nodes" select="$root-nodes"/>
</xsl:call-template>
<xsl:apply-templates select="$root-nodes" mode="toc">
<xsl:with-param name="toc-context" select="$toc-context"/>
</xsl:apply-templates>
</xsl:element>
</div>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
注意:还有一个问题,即并非每个分块页面都有自己的目录,但这与此具体无关。如果我对它进行排序,我会添加评论说明我是如何做到的。