<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:pf="http://www.daisy.org/ns/pipeline/functions" xmlns:d="http://www.daisy.org/ns/pipeline/data" xmlns:dtbook="http://www.daisy.org/z3986/2005/dtbook/" xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2.0" exclude-result-prefixes="#all"> <xsl:import href="http://www.daisy.org/pipeline/modules/file-utils/library.xsl"/> <xsl:param name="ncx-dir"/> <xsl:param name="uid"/> <xsl:param name="fail-if-missing-smilref"/> <xsl:key name="id" match="*[@id]" use="@id"/> <xsl:variable name="titles" select="' levelhd hd h1 h2 h3 h4 h5 h6 '"/> <xsl:variable name="navPoints" select="' level level1 level2 level3 level4 level5 level6 '"/> <xsl:variable name="pageTargets" select="' pagenum '"/> <xsl:variable name="content-doc" select="/*"/> <xsl:variable name="content-doc-uri" select="pf:normalize-uri(base-uri($content-doc))"/> <xsl:variable name="audio-map" as="document-node(element(d:audio-clips))"> <xsl:variable name="audio-map" select="collection()[/d:audio-clips]"/> <xsl:document> <xsl:for-each select="$audio-map/*"> <xsl:variable name="audio-map-uri" select="base-uri(.)"/> <xsl:copy> <xsl:for-each-group select="*" group-by="@src"> <xsl:variable name="src" select="current-grouping-key()"/> <xsl:variable name="src" select="resolve-uri($src,$audio-map-uri)"/> <xsl:variable name="src" select="pf:relativize-uri($src,$ncx-dir)"/> <xsl:for-each select="current-group()"> <xsl:copy> <xsl:sequence select="@* except (@src,@textref)"/> <xsl:attribute name="src" select="$src"/> <xsl:attribute name="textref" select="pf:normalize-uri(resolve-uri(@textref,$audio-map-uri))"/> </xsl:copy> </xsl:for-each> </xsl:for-each-group> </xsl:copy> </xsl:for-each> </xsl:document> </xsl:variable> <xsl:variable name="navTargets"> <targets> <target type="note"/> </targets> </xsl:variable> <xsl:variable name="all-but-headings" select="concat(' ', string-join($navTargets//@type, ' '), ' ', $pageTargets)"/> <xsl:variable name="pages" as="element()*"> <xsl:variable name="page-list" as="document-node(element(d:fileset))?" select="collection()[3]"/> <xsl:choose> <xsl:when test="exists($page-list)"> <xsl:for-each select="$page-list//d:file[pf:normalize-uri(resolve-uri(@href,base-uri(.)))=$content-doc-uri]/d:anchor"> <xsl:sequence select="key('id',@id,$content-doc)"/> </xsl:for-each> </xsl:when> <xsl:otherwise> <xsl:sequence select="//dtbook:pagenum"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:key name="clips" match="d:clip" use="@textref"/> <xsl:key name="headings" use="generate-id()" match="*[contains($navPoints, concat(' ', local-name(), ' ')) and *[contains($titles, concat(' ', local-name(), ' '))]]"/> <xsl:variable name="play-orders"> <d:playOrders> <xsl:for-each select="//*[key('headings', generate-id()) or contains($all-but-headings, concat(' ', local-name(), ' '))]"> <d:o v="{position()}" id="{generate-id()}"/> </xsl:for-each> </d:playOrders> </xsl:variable> <xsl:key name="orders" use="@id" match="*[@id]"/> <xsl:function name="d:getText"> <xsl:param name="container"/> <xsl:value-of select="normalize-space(string-join($container/descendant-or-self::text(), ''))"/> </xsl:function> <xsl:template match="/"> <ncx version="2005-1"> <head> <meta content="DAISY Pipeline 2" name="dtb:generator"/> <meta name="dtb:uid" content="{$uid}"/> <meta name="dtb:depth" content="{concat('0', max(//*[key('headings', generate-id())]/ count(ancestor-or-self::*[key('headings', generate-id())])))}"/> <xsl:variable name="total-pages" select="count($pages)"/> <meta name="dtb:totalPageCount" content="{$total-pages}"/> <meta name="dtb:maxPageNumber" content="{$total-pages}"/> <smilCustomTest bookStruct="PAGE_NUMBER" defaultState="false" id="pagenum" override="visible"/> <smilCustomTest bookStruct="NOTE" defaultState="false" id="note" override="visible"/> <smilCustomTest bookStruct="NOTE_REFERENCE" defaultState="false" id="noteref" override="visible"/> <smilCustomTest bookStruct="ANNOTATION" defaultState="false" id="annotation" override="visible"/> <smilCustomTest bookStruct="LINE_NUMBER" defaultState="false" id="linenum" override="visible"/> <smilCustomTest bookStruct="OPTIONAL_SIDEBAR" defaultState="false" id="sidebar" override="visible"/> <smilCustomTest bookStruct="OPTIONAL_PRODUCER_NOTE" defaultState="false" id="prodnote" override="visible"/> </head> <docTitle> <xsl:apply-templates mode="add-text" select="(//dtbook:doctitle)[1]"/> </docTitle> <xsl:apply-templates select="//dtbook:docauthor" mode="author"/> <navMap> <xsl:choose> <xsl:when test="not(($play-orders//*[@id])[1]) or not((//*[key('headings', generate-id())])[1])"> <navPoint playOrder="{count($play-orders//*[@id]) + 1}" id="fake-navPoint"> <navLabel><text>Error: no headings</text></navLabel> <xsl:apply-templates mode="add-content-link" select="(//*[@smilref and not(key('orders', generate-id(), $play-orders))])[1]"/> </navPoint> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="*" mode="navMap"> <xsl:with-param name="play-orders" select="$play-orders"/> </xsl:apply-templates> </xsl:otherwise> </xsl:choose> </navMap> <xsl:call-template name="pageList"> <xsl:with-param name="play-orders" select="$play-orders"/> </xsl:call-template> <xsl:call-template name="navList"> <xsl:with-param name="play-orders" select="$play-orders"/> </xsl:call-template> </ncx> </xsl:template> <xsl:template match="*" mode="author"> <docAuthor> <xsl:apply-templates mode="add-text" select="."/> </docAuthor> </xsl:template> <xsl:template match="*" mode="navMap"> <xsl:param name="play-orders"/> <xsl:apply-templates select="*" mode="navMap"> <xsl:with-param name="play-orders" select="$play-orders"/> </xsl:apply-templates> </xsl:template> <xsl:template match="*[key('headings', generate-id())]" mode="navMap"> <xsl:param name="play-orders"/> <navPoint> <xsl:apply-templates select="." mode="add-content"> <xsl:with-param name="play-orders" select="$play-orders"/> <xsl:with-param name="text-container" select="*[contains($titles, concat(' ', local-name(), ' '))][1]"/> </xsl:apply-templates> <xsl:apply-templates select="*" mode="navMap"> <xsl:with-param name="play-orders" select="$play-orders"/> </xsl:apply-templates> </navPoint> </xsl:template> <xsl:template name="pageList"> <xsl:param name="play-orders"/> <xsl:if test="$pages"> <pageList> <xsl:for-each select="$pages"> <xsl:variable name="val" select="d:getText(.)"/> <pageTarget type="{if (@page) then @page else 'normal'}" value="{position()}"> <xsl:apply-templates select="." mode="add-content"> <xsl:with-param name="play-orders" select="$play-orders"/> <xsl:with-param name="text-container" select="."/> </xsl:apply-templates> </pageTarget> </xsl:for-each> </pageList> </xsl:if> </xsl:template> <xsl:template name="navList"> <xsl:param name="play-orders"/> <xsl:param name="doc-context" select="/"/> <xsl:for-each select="$navTargets//*[@type]"> <xsl:variable name="type" select="@type"/> <xsl:variable name="targets" select="$doc-context//*[local-name() = $type]"/> <xsl:if test="$targets"> <navList class="{$type}"> <navLabel><text><xsl:value-of select="@type"/></text></navLabel> <xsl:for-each select="$targets"> <navTarget> <xsl:apply-templates select="." mode="add-content"> <xsl:with-param name="play-orders" select="$play-orders"/> <xsl:with-param name="text-container" select="."/> </xsl:apply-templates> </navTarget> </xsl:for-each> </navList> </xsl:if> </xsl:for-each> </xsl:template> <xsl:template match="*" mode="add-content"> <xsl:param name="play-orders"/> <xsl:param name="text-container"/> <xsl:variable name="play-order" select="key('orders', generate-id(), $play-orders)/@v"/> <xsl:attribute name="playOrder"> <xsl:value-of select="$play-order"/> </xsl:attribute> <xsl:attribute name="id"> <xsl:value-of select="concat('ncx-', $play-order)"/> </xsl:attribute> <navLabel> <xsl:apply-templates select="$text-container" mode="add-text"/> </navLabel> <xsl:apply-templates select="$text-container" mode="add-content-link"/> </xsl:template> <xsl:template match="*" mode="add-content-link"> <xsl:choose> <xsl:when test="@smilref"> <content src="{pf:relativize-uri(resolve-uri(@smilref,$content-doc-uri),$ncx-dir)}"/> </xsl:when> <xsl:when test="$fail-if-missing-smilref='true'"> <xsl:message terminate="yes">ERROR: NCX contains entry without content link</xsl:message> </xsl:when> </xsl:choose> </xsl:template> <xsl:template match="*" mode="add-text"> <text> <xsl:value-of select="d:getText(.)"/> </text> <xsl:variable name="all-clips" as="element(d:clip)*"> <xsl:for-each select="descendant-or-self::*[@id]"> <xsl:variable name="textref" select="concat($content-doc-uri,'#',@id)"/> <xsl:sequence select="key('clips',$textref,$audio-map)[1]"/> </xsl:for-each> </xsl:variable> <xsl:if test="count($all-clips) > 0"> <xsl:variable name="first-clip" as="element(d:clip)" select="$all-clips[1]"/> <xsl:variable name="last-clip" as="element(d:clip)" select="$all-clips[last()]"/> <xsl:if test="$first-clip/@src = $last-clip/@src"> <audio> <xsl:sequence select="$first-clip/(@src|@clipBegin|@clipEnd)"/> </audio> </xsl:if> </xsl:if> </xsl:template> </xsl:stylesheet>