1

我有一堆 DocBook XML 文件,它们都被合并到一个 DocBook 文件中以转换为 HTML。每个单独的文档都是一个参考页(用于功能或类似结构)。我使用分块的 HTML 生成,以便每个参考页面成为它自己的 HTML 页面。

问题是这样的:我想要每个页面上的目录。但我不想要那个页面的目录。我想要整个参考手册的完整目录。

也就是说,从任何页面,我都希望能够使用 TOC 跳转到任何其他页面。我可以使用 CSS 样式将 TOC 粘贴在左侧(甚至隐藏它以供移动查看或其他任何内容)。

有一个明显的方法来处理这个。我可以通过后处理脚本提取主 TOC,并让脚本将其复制到每个输出 HTML 文档中。我正在寻找的是一种在 DocBook XSL 中工作的方法。

我希望结果看起来更像DocBook XSL 的较新的 webhelp,但不那么明显地涉及 JavaScript。

4

2 回答 2

2

截至 2019 年 7 月 6 日,使用 docbook-xsl-1.79.2 目前接受的答案不足以使每个目录都完整。

但是,以下 XSL 模板可以。关键的见解是逐步使用 Oxygen XML 编辑器的调试器,并注意到虽然toc-context已正确设置为根元素,但该nodes变量仍然是本地子集。

我取消了toc-context更改。相反,我创建了一个新变量root-nodesselection /,并编辑了make.toc要使用的模板,root-nodes而不是nodes.

现在将它放在我的自定义层中,可以使每个目录成为一个完整的目录。

<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>

注意:还有一个问题,不是每个分块页面都有自己的 ToC,但这与具体情况无关。如果我对它进行排序,我会添加评论我是如何做到的。

于 2019-07-06T19:02:27.750 回答
1

有一个相对简单的方法来获得它,尽管我很确定您不能不创建 DocBook XSL 自定义层或直接修改已安装的(系统)样式表。

无论哪种方式,我认为您需要修改或覆盖的实际 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 时,它应该只查看当前正在处理的任何元素的(子)内容(即,该特定块的根);例如,如果它正在处理 asection它只会查看 that 的孩子section

但是,如果您改为将该值更改为“ /”,您就是在告诉模板每次(重新)查看源文档的全部内容。因此,如果您的文档是book,它每次都会为您提供整本书的整个 TOC,或者如果您的文档是article,则为整篇文章等。

所以我认为这应该给你你想要的。

如果您决定只修改已安装的样式表,并且您已经从您使用的任何特定于操作系统的包管理器中安装了它们,那么您需要找到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

如果您决定改为创建自定义层,则需要将整个make.toc模板复制到自定义层中(但将该toc-context参数更改为“ /”)。

于 2015-12-26T00:37:25.917 回答