#1134 epub: toc.max.depth not used to create toc.ncx

output: ePub
open
XSL (1066)
5
2011-08-28
2010-09-20
Oliver K. Smith
No

When creating an epub file, the toc.max.depth parameter is not used when generating the toc.ncx file.

This results in a very large Table of Contents in documents which have many sections. On a mobile device, this can make the Table of Contents almost unusable.

Please consider support for this parameter.

Thanks.

Discussion

  • I think I have a fix for the problem. In the file docbook-xsl-ns/epub/docbook.xsl, make the following change:

    CHANGE:

    <xsl:template match="d:book|
    d:article|
    d:part|
    d:reference|
    d:preface|
    d:chapter|
    d:bibliography|
    d:appendix|
    d:glossary|
    d:section|
    d:sect1|
    d:sect2|
    d:sect3|
    d:sect4|
    d:sect5|
    d:refentry|
    d:colophon|
    d:bibliodiv[d:title]|
    d:setindex|
    d:index"
    mode="ncx">
    <xsl:variable name="depth" select="count(ancestor::*)"/>
    <xsl:variable name="title">
    <xsl:if test="$epub.autolabel != 0">
    <xsl:variable name="label.markup">
    <xsl:apply-templates select="." mode="label.markup" />
    </xsl:variable>
    <xsl:if test="normalize-space($label.markup)">
    <xsl:value-of
    select="concat($label.markup,$autotoc.label.separator)" />
    </xsl:if>
    </xsl:if>
    <xsl:apply-templates select="." mode="title.markup" />
    </xsl:variable>

    <xsl:variable name="href">
    <xsl:call-template name="href.target.with.base.dir">
    <xsl:with-param name="context" select="/" />
    <!-- Generate links relative to the location of root file/toc.xml file -->
    </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="id">
    <xsl:value-of select="generate-id(.)"/>
    </xsl:variable>
    <xsl:variable name="order">
    <xsl:value-of select="$depth +
    count(preceding::d:part|
    preceding::d:reference|
    preceding::d:book[parent::d:set]|
    preceding::d:preface|
    preceding::d:chapter|
    preceding::d:bibliography|
    preceding::d:appendix|
    preceding::d:article|
    preceding::d:glossary|
    preceding::d:section[not(parent::d:partintro)]|
    preceding::d:sect1[not(parent::d:partintro)]|
    preceding::d:sect2[not(ancestor::d:partintro)]|
    preceding::d:sect3[not(ancestor::d:partintro)]|
    preceding::d:sect4[not(ancestor::d:partintro)]|
    preceding::d:sect5[not(ancestor::d:partintro)]|
    preceding::d:refentry|
    preceding::d:colophon|
    preceding::d:bibliodiv[d:title]|
    preceding::d:index)"/>
    </xsl:variable>

    <xsl:element name="navPoint" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:attribute name="id">
    <xsl:value-of select="$id"/>
    </xsl:attribute>

    <xsl:attribute name="playOrder">
    <xsl:choose>
    <xsl:when test="/*[self::d:set]">
    <xsl:value-of select="$order"/>
    </xsl:when>
    <xsl:when test="$root.is.a.chunk != '0'">
    <xsl:value-of select="$order + 1"/>
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="$order - 0"/>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:attribute>
    <xsl:element name="navLabel" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:element name="text" namespace="http://www.daisy.org/z3986/2005/ncx/"><xsl:value-of select="normalize-space($title)"/> </xsl:element>
    </xsl:element>
    <xsl:element name="content" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:attribute name="src">
    <xsl:value-of select="$href"/>
    </xsl:attribute>
    </xsl:element>
    <xsl:apply-templates select="d:book[parent::d:set]|d:part|d:reference|d:preface|d:chapter|d:bibliography|d:appendix|d:article|d:glossary|d:section|d:sect1|d:sect2|d:sect3|d:sect4|d:sect5|d:refentry|d:colophon|d:bibliodiv[d:title]|d:setindex|d:index" mode="ncx"/>
    </xsl:element>

    </xsl:template>

    TO:

    <xsl:template match="d:book|
    d:article|
    d:part|
    d:reference|
    d:preface|
    d:chapter|
    d:bibliography|
    d:appendix|
    d:glossary|
    d:section|
    d:sect1|
    d:sect2|
    d:sect3|
    d:sect4|
    d:sect5|
    d:refentry|
    d:colophon|
    d:bibliodiv[d:title]|
    d:setindex|
    d:index"
    mode="ncx">
    <xsl:variable name="depth" select="count(ancestor::*)"/>
    <xsl:variable name="title">
    <xsl:if test="$epub.autolabel != 0">
    <xsl:variable name="label.markup">
    <xsl:apply-templates select="." mode="label.markup" />
    </xsl:variable>
    <xsl:if test="normalize-space($label.markup)">
    <xsl:value-of
    select="concat($label.markup,$autotoc.label.separator)" />
    </xsl:if>
    </xsl:if>
    <xsl:apply-templates select="." mode="title.markup" />
    </xsl:variable>

    <xsl:variable name="href">
    <xsl:call-template name="href.target.with.base.dir">
    <xsl:with-param name="context" select="/" />
    <!-- Generate links relative to the location of root file/toc.xml file -->
    </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="id">
    <xsl:value-of select="generate-id(.)"/>
    </xsl:variable>

    <xsl:if test="$depth &lt;= $toc.max.depth">

    <xsl:variable name="order">
    <xsl:value-of select="count(preceding::*[count(ancestor::*) &lt;= $toc.max.depth])"/>
    </xsl:variable>

    <xsl:element name="navPoint" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:attribute name="id">
    <xsl:value-of select="$id"/>
    </xsl:attribute>

    <xsl:attribute name="playOrder">
    <xsl:choose>
    <xsl:when test="/*[self::d:set]">
    <xsl:value-of select="$order"/>
    </xsl:when>
    <xsl:when test="$root.is.a.chunk != '0'">
    <xsl:value-of select="$order + 1"/>
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="$order - 0"/>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:attribute>
    <xsl:element name="navLabel" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:element name="text" namespace="http://www.daisy.org/z3986/2005/ncx/"><xsl:value-of select="normalize-space($title)"/> </xsl:element>
    </xsl:element>
    <xsl:element name="content" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:attribute name="src">
    <xsl:value-of select="$href"/>
    </xsl:attribute>
    </xsl:element>
    <xsl:apply-templates select="d:book[parent::d:set]|d:part|d:reference|d:preface|d:chapter|d:bibliography|d:appendix|d:article|d:glossary|d:section|d:sect1|d:sect2|d:sect3|d:sect4|d:sect5|d:refentry|d:colophon|d:bibliodiv[d:title]|d:setindex|d:index" mode="ncx"/>
    </xsl:element>

    </xsl:if>

    </xsl:template>

    This change causes the parameter toc.max.depth to control the depth of the Table of Contents in the toc.ncx file.

    Attached is a patch file which can be applied to the docbook.xsl file that was attached to bug #3071521.

    The patch file also includes the fixes described in bugs #3071937 and #3072388.

    Also is attached a copy of this note.

    Thanks.

     
  • Ooops.

    Please accept my humblest apologies. Yes, I'm embarrassed.

    I inadequately tested my proposed solution.

    I am not an XPath expert. Perhaps you could help.

    In the expression below,

    <xsl:variable name="order">
    <xsl:value-of select="count(preceding::*[count(ancestor::*) &lt;= $toc.max.depth])"/>
    </xsl:variable>

    each of the nodes returned by:

    ancestor::*

    must be filtered by:

    d:book|
    d:article|
    d:part|
    d:reference|
    d:preface|
    d:chapter|
    d:bibliography|
    d:appendix|
    d:glossary|
    d:section|
    d:sect1|
    d:sect2|
    d:sect3|
    d:sect4|
    d:sect5|
    d:refentry|
    d:colophon|
    d:bibliodiv[d:title]|
    d:setindex|
    d:index

    before it is counted. In other words, only ancestors that meet the above criteria should be counted.

    I don't know how to write this expression. If you do, please let me know.

    Otherwise, please ignore my well intentioned proposed solution.

    Thanks for your patience.

     
  • tests for proposed enhancement

     
    Attachments
    • labels: 1168228 --> XSL
     
  • Having embarrassed myself by submitting a poorly tested enhancement, I now submit this enhancement I that I have tested.

    I am supplying the tests I used to verify this.

    Presently there is no mechanism in the

    docbook-xsl-ns/epub/docbook.xsl

    stylesheet to limit the depth of the Table of Contents in the toc.ncx file.

    This can be done by editing the file:

    docbook-xsl-ns/epub/docbook.xsl

    attached to Bug #3071521, in the following manner:

    CHANGE:

    <xsl:template match="d:book|
    d:article|
    d:part|
    d:reference|
    d:preface|
    d:chapter|
    d:bibliography|
    d:appendix|
    d:glossary|
    d:section|
    d:sect1|
    d:sect2|
    d:sect3|
    d:sect4|
    d:sect5|
    d:refentry|
    d:colophon|
    d:bibliodiv[d:title]|
    d:setindex|
    d:index"
    mode="ncx">
    <xsl:variable name="depth" select="count(ancestor::*)"/>
    <xsl:variable name="title">
    <xsl:if test="$epub.autolabel != 0">
    <xsl:variable name="label.markup">
    <xsl:apply-templates select="." mode="label.markup" />
    </xsl:variable>
    <xsl:if test="normalize-space($label.markup)">
    <xsl:value-of
    select="concat($label.markup,$autotoc.label.separator)" />
    </xsl:if>
    </xsl:if>
    <xsl:apply-templates select="." mode="title.markup" />
    </xsl:variable>

    <xsl:variable name="href">
    <xsl:call-template name="href.target.with.base.dir">
    <xsl:with-param name="context" select="/" />
    <!-- Generate links relative to the location of root file/toc.xml file -->
    </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="id">
    <xsl:value-of select="generate-id(.)"/>
    </xsl:variable>
    <xsl:variable name="order">
    <xsl:value-of select="$depth +
    count(preceding::d:part|
    preceding::d:reference|
    preceding::d:book[parent::d:set]|
    preceding::d:preface|
    preceding::d:chapter|
    preceding::d:bibliography|
    preceding::d:appendix|
    preceding::d:article|
    preceding::d:glossary|
    preceding::d:section[not(parent::d:partintro)]|
    preceding::d:sect1[not(parent::d:partintro)]|
    preceding::d:sect2[not(ancestor::d:partintro)]|
    preceding::d:sect3[not(ancestor::d:partintro)]|
    preceding::d:sect4[not(ancestor::d:partintro)]|
    preceding::d:sect5[not(ancestor::d:partintro)]|
    preceding::d:refentry|
    preceding::d:colophon|
    preceding::d:bibliodiv[d:title]|
    preceding::d:index)"/>
    </xsl:variable>

    <xsl:element name="navPoint" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:attribute name="id">
    <xsl:value-of select="$id"/>
    </xsl:attribute>

    <xsl:attribute name="playOrder">
    <xsl:choose>
    <xsl:when test="/*[self::d:set]">
    <xsl:value-of select="$order"/>
    </xsl:when>
    <xsl:when test="$root.is.a.chunk != '0'">
    <xsl:value-of select="$order + 1"/>
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="$order - 0"/>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:attribute>
    <xsl:element name="navLabel" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:element name="text" namespace="http://www.daisy.org/z3986/2005/ncx/"><xsl:value-of select="normalize-space($title)"/> </xsl:element>
    </xsl:element>
    <xsl:element name="content" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:attribute name="src">
    <xsl:value-of select="$href"/>
    </xsl:attribute>
    </xsl:element>
    <xsl:apply-templates select="d:book[parent::d:set]|d:part|d:reference|d:preface|d:chapter|d:bibliography|d:appendix|d:article|d:glossary|d:section|d:sect1|d:sect2|d:sect3|d:sect4|d:sect5|d:refentry|d:colophon|d:bibliodiv[d:title]|d:setindex|d:index" mode="ncx"/>
    </xsl:element>

    </xsl:template>

    TO:

    <xsl:template match="d:book|
    d:article|
    d:part|
    d:reference|
    d:preface|
    d:chapter|
    d:bibliography|
    d:appendix|
    d:glossary|
    d:section|
    d:sect1|
    d:sect2|
    d:sect3|
    d:sect4|
    d:sect5|
    d:refentry|
    d:colophon|
    d:bibliodiv[d:title]|
    d:setindex|
    d:index"
    mode="ncx">
    <xsl:variable name="depth" select="count(ancestor::*)"/>
    <xsl:variable name="title">
    <xsl:if test="$epub.autolabel != 0">
    <xsl:variable name="label.markup">
    <xsl:apply-templates select="." mode="label.markup" />
    </xsl:variable>
    <xsl:if test="normalize-space($label.markup)">
    <xsl:value-of
    select="concat($label.markup,$autotoc.label.separator)" />
    </xsl:if>
    </xsl:if>
    <xsl:apply-templates select="." mode="title.markup" />
    </xsl:variable>

    <xsl:if test="$depth &lt;= $toc.max.depth">

    <xsl:variable name="href">
    <xsl:call-template name="href.target.with.base.dir">
    <xsl:with-param name="context" select="/" />
    <!-- Generate links relative to the location of root file/toc.xml file -->
    </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="id">
    <xsl:value-of select="generate-id(.)"/>
    </xsl:variable>
    <xsl:variable name="order">
    <xsl:value-of select="$depth +
    count(preceding::d:part[count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:reference[count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:book[parent::d:set][count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:preface[count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:chapter[count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:bibliography[count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:appendix[count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:article[count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:glossary[count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:section[not(parent::d:partintro)][count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:sect1[not(parent::d:partintro)][count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:sect2[not(ancestor::d:partintro)][count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:sect3[not(ancestor::d:partintro)][count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:sect4[not(ancestor::d:partintro)][count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:sect5[not(ancestor::d:partintro)][count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:refentry[count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:colophon[count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:bibliodiv[d:title][count(ancestor::*) &lt;= $toc.max.depth]|
    preceding::d:index[count(ancestor::*) &lt;= $toc.max.depth])"/>
    </xsl:variable>

    <xsl:element name="navPoint" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:attribute name="id">
    <xsl:value-of select="$id"/>
    </xsl:attribute>

    <xsl:attribute name="playOrder">
    <xsl:choose>
    <xsl:when test="/*[self::d:set]">
    <xsl:value-of select="$order"/>
    </xsl:when>
    <xsl:when test="$root.is.a.chunk != '0'">
    <xsl:value-of select="$order + 1"/>
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="$order - 0"/>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:attribute>
    <xsl:element name="navLabel" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:element name="text" namespace="http://www.daisy.org/z3986/2005/ncx/"><xsl:value-of select="normalize-space($title)"/> </xsl:element>
    </xsl:element>
    <xsl:element name="content" namespace="http://www.daisy.org/z3986/2005/ncx/">
    <xsl:attribute name="src">
    <xsl:value-of select="$href"/>
    </xsl:attribute>
    </xsl:element>
    <xsl:apply-templates select="d:book[parent::d:set]|d:part|d:reference|d:preface|d:chapter|d:bibliography|d:appendix|d:article|d:glossary|d:section|d:sect1|d:sect2|d:sect3|d:sect4|d:sect5|d:refentry|d:colophon|d:bibliodiv[d:title]|d:setindex|d:index" mode="ncx"/>
    </xsl:element>

    </xsl:if>

    </xsl:template>

    This modification allows the depth of the Table of Contents in the toc.ncx file to be controlled by the parameter:

    $toc.max.depth

    I have tested this with a sample book, a sample, set, and two sample books.

    All of the example files were validated with relames.

    The resulting epubfiles were verified with epubcheck.

    Please accept my humblest apologies for begin a zealot and previously submitting inadequately tested code.

    A copy of these notes appear in the archive named epub_toc_test.zip.

    At patch file which can be applied to the docbook.xsl attached to Bug #3071521 is in the archive.

    Unfortunately, due to upload file size restrictions on Sourceforge, only the generated results for the "book" example are provided.

    I hope this enhancement will be deemed a worthy inclusion in the Docbook stylesheets.

    If you need more information about this, please don't hesitate to ask.

    Thanks.

     
    • summary: toc.max.depth not used to create toc.ncx --> epub: toc.max.depth not used to create toc.ncx