<
xsl:stylesheet xmlns:xsl=
"http://www.w3.org/1999/XSL/Transform" xmlns:xs=
"http://www.w3.org/2001/XMLSchema" xmlns:d=
"http://www.daisy.org/ns/pipeline/data" xmlns:f=
"http://www.daisy.org/ns/pipeline/internal-functions" xmlns:pf=
"http://www.daisy.org/ns/pipeline/functions" xmlns:tts=
"http://www.daisy.org/ns/pipeline/tts" xmlns:epub=
"http://www.idpf.org/2007/ops" xmlns=
"http://www.w3.org/1999/xhtml" version=
"2.0" xpath-default-namespace=
"http://www.w3.org/1999/xhtml" exclude-result-prefixes=
"#all">
<
xsl:import href=
"http://www.daisy.org/pipeline/modules/file-utils/library.xsl"/>
<
xsl:include href=
"untitled-section-titles.xsl"/>
<
xsl:param name=
"output-base-uri" required=
"yes"/>
<
xsl:param name=
"heading-links-only" required=
"yes"/>
<
xsl:param name=
"fix-untitled-sections-in-outline" required=
"yes"/>
<
xsl:key name=
"id" match=
"*" use=
"@id"/>
<
xsl:template match=
"/">
<
xsl:variable name=
"outline" as=
"element(d:outline)">
<
xsl:call-template name=
"get-outline"/>
</
xsl:variable>
<
xsl:call-template name=
"format-outline">
<
xsl:with-param name=
"outline" select=
"$outline"/>
</
xsl:call-template>
<
xsl:result-document method=
"xml" href=
"outline">
<
xsl:sequence select=
"$outline"/>
</
xsl:result-document>
</
xsl:template>
<
xsl:template name=
"get-outline" as=
"element(d:outline)">
<
xsl:variable name=
"filtered" as=
"element(body)">
<
xsl:apply-templates mode=
"filter" select=
"/html/body"/>
</
xsl:variable>
<
xsl:apply-templates mode=
"outline" select=
"$filtered"/>
</
xsl:template>
<
xsl:template name=
"format-outline">
<
xsl:param name=
"outline" as=
"element(d:outline)" required=
"yes"/>
<
xsl:variable name=
"input-base-uri" select=
"base-uri(/*)"/>
<
xsl:variable name=
"relative-path" select=
"pf:relativize-uri($input-base-uri, $output-base-uri)"/>
<
xsl:variable name=
"ol" as=
"element(ol)">
<
ol>
<
xsl:apply-templates select=
"$outline">
<
xsl:with-param name=
"html-doc" tunnel=
"yes" select=
"root()"/>
<
xsl:with-param name=
"relative-path" tunnel=
"yes" select=
"$relative-path"/>
</
xsl:apply-templates>
</
ol>
</
xsl:variable>
<
xsl:choose>
<
xsl:when test=
"$fix-untitled-sections-in-outline='unwrap'">
<
xsl:apply-templates mode=
"clean" select=
"$ol"/>
</
xsl:when>
<
xsl:otherwise>
<
xsl:sequence select=
"$ol"/>
</
xsl:otherwise>
</
xsl:choose>
</
xsl:template>
<
xsl:template match=
"html">
<
xsl:variable name=
"outline" as=
"element(d:outline)">
<
xsl:call-template name=
"get-outline"/>
</
xsl:variable>
<
xsl:call-template name=
"format-outline">
<
xsl:with-param name=
"outline" select=
"$outline"/>
</
xsl:call-template>
</
xsl:template>
<
xsl:template mode=
"filter" match=
"body">
<
xsl:copy>
<
xsl:sequence select=
"@*"/>
<
xsl:apply-templates mode=
"#current" select=
"*"/>
</
xsl:copy>
</
xsl:template>
<
xsl:template mode=
"filter" match=
"blockquote|details|fieldset|figure|td"/>
<
xsl:template mode=
"filter" match=
"article|aside|nav|section">
<
xsl:copy>
<
xsl:sequence select=
"@*"/>
<
xsl:apply-templates mode=
"#current" select=
"*"/>
</
xsl:copy>
</
xsl:template>
<
xsl:template mode=
"filter" match=
"h1|h2|h3|h4|h5|h6|hgroup">
<
xsl:copy>
<
xsl:sequence select=
"@*|node()"/>
</
xsl:copy>
</
xsl:template>
<
xsl:template mode=
"filter" match=
"*">
<
xsl:apply-templates mode=
"#current" select=
"*"/>
</
xsl:template>
<
xsl:template mode=
"outline" match=
"body| article|aside|nav|section">
<
d:outline owner=
"{@id}">
<
xsl:call-template name=
"sections">
<
xsl:with-param name=
"outline-owner" select=
"."/>
</
xsl:call-template>
</
d:outline>
</
xsl:template>
<
xsl:template name=
"sections" as=
"element(d:section)*">
<
xsl:param name=
"outline-owner" as=
"element()?" select=
"()"/>
<
xsl:param name=
"content" as=
"element()*" select=
"$outline-owner/*"/>
<
xsl:choose>
<
xsl:when test=
"not(exists($outline-owner)) and not(exists($content) and f:is-heading($content[1]))">
<
xsl:message terminate=
"yes">coding error</
xsl:message>
</
xsl:when>
<
xsl:when test=
"not(exists($content))">
<
d:section owner=
"{$outline-owner/@id}"/>
</
xsl:when>
<
xsl:otherwise>
<
xsl:variable name=
"first-heading" as=
"element()?" select=
"$content[f:is-heading(.)][1] [not(preceding-sibling::*[f:is-section(.)] intersect $content)]"/>
<
xsl:for-each-group select=
"$content" group-starting-with=
"*[f:is-heading(.)] [f:rank(.) >= max((0,(preceding-sibling::* intersect $content)/f:rank(.)))]">
<
xsl:choose>
<
xsl:when test=
"position()=1">
<
d:section>
<
xsl:if test=
"exists($outline-owner)">
<
xsl:attribute name=
"owner" select=
"$outline-owner/@id"/>
</
xsl:if>
<
xsl:if test=
"exists($first-heading)">
<
xsl:attribute name=
"heading" select=
"($first-heading/@id, $first-heading[not(preceding-sibling::*)]/parent::*/@id)[1]"/>
</
xsl:if>
<
xsl:for-each-group select=
"current-group() except $first-heading" group-adjacent=
"f:is-section(.)">
<
xsl:choose>
<
xsl:when test=
"f:is-section(.)">
<
xsl:apply-templates mode=
"#current" select=
"current-group()"/>
</
xsl:when>
<
xsl:otherwise>
<
xsl:call-template name=
"sections">
<
xsl:with-param name=
"content" select=
"current-group()"/>
</
xsl:call-template>
</
xsl:otherwise>
</
xsl:choose>
</
xsl:for-each-group>
</
d:section>
</
xsl:when>
<
xsl:otherwise>
<
xsl:call-template name=
"sections">
<
xsl:with-param name=
"content" select=
"current-group()"/>
</
xsl:call-template>
</
xsl:otherwise>
</
xsl:choose>
</
xsl:for-each-group>
</
xsl:otherwise>
</
xsl:choose>
</
xsl:template>
<
xsl:template match=
"d:outline">
<
xsl:apply-templates select=
"*"/>
</
xsl:template>
<
xsl:template match=
"d:section">
<
xsl:param name=
"html-doc" tunnel=
"yes" as=
"document-node()" required=
"yes"/>
<
xsl:param name=
"relative-path" tunnel=
"yes" as=
"xs:string" required=
"yes"/>
<
xsl:if test=
"not(@owner) and not(@heading)">
<
xsl:message terminate=
"yes">coding error</
xsl:message>
</
xsl:if>
<
xsl:variable name=
"heading" as=
"element()?" select=
"key('id',@heading,$html-doc)"/>
<
xsl:variable name=
"heading" as=
"element()?" select=
"for $h in $heading return if (f:is-heading($h)) then $h else $h/*[f:is-heading(.)][1]"/>
<
xsl:choose>
<
xsl:when test=
"not($heading/descendant-or-self::text()) and $fix-untitled-sections-in-outline='unwrap'">
<
xsl:apply-templates select=
"*"/>
</
xsl:when>
<
xsl:otherwise>
<
li>
<
xsl:element namespace=
"http://www.w3.org/1999/xhtml" name=
"{if ($heading-links-only='true' and not(@heading)) then 'span' else 'a'}">
<
xsl:choose>
<
xsl:when test=
"$heading-links-only='true'">
<
xsl:if test=
"@heading">
<
xsl:attribute name=
"href" select=
"concat($relative-path,'#',@heading)"/>
</
xsl:if>
</
xsl:when>
<
xsl:otherwise>
<
xsl:attribute name=
"href" select=
"concat($relative-path,'#',(@owner,@heading)[1])"/>
</
xsl:otherwise>
</
xsl:choose>
<
xsl:sequence select=
"$heading/ancestor-or-self::*/@tts:*"/>
<
xsl:choose>
<
xsl:when test=
"$heading/descendant-or-self::text()">
<
xsl:choose>
<
xsl:when test=
"$heading[self::h1 or self::h2 or self::h3 or self::h4 or self::h5 or self::h6]">
<
xsl:apply-templates select=
"$heading/(*|text())"/>
</
xsl:when>
<
xsl:when test=
"$heading[self::hgroup]">
<
xsl:variable name=
"rank" select=
"f:rank($heading)"/>
<
xsl:variable name=
"heading" select=
"$heading/*[f:rank(.)=$rank][1]"/>
<
xsl:apply-templates select=
"$heading/(*|text())"/>
</
xsl:when>
</
xsl:choose>
</
xsl:when>
<
xsl:when test=
"@owner">
<
xsl:variable name=
"owner" as=
"element()" select=
"key('id',@owner,$html-doc)"/>
<
xsl:choose>
<
xsl:when test=
"$owner/@aria-label">
<
xsl:value-of select=
"$owner/@aria-label"/>
</
xsl:when>
<
xsl:otherwise>
<
xsl:call-template name=
"get-untitled-section-title">
<
xsl:with-param name=
"sectioning-element" select=
"$owner"/>
</
xsl:call-template>
</
xsl:otherwise>
</
xsl:choose>
</
xsl:when>
<
xsl:otherwise>
<
xsl:sequence select=
"'Untitled section'"/>
</
xsl:otherwise>
</
xsl:choose>
</
xsl:element>
<
xsl:if test=
"exists(*)">
<
ol>
<
xsl:apply-templates select=
"*"/>
</
ol>
</
xsl:if>
</
li>
</
xsl:otherwise>
</
xsl:choose>
</
xsl:template>
<
xsl:template match=
"a">
<
xsl:variable name=
"content" as=
"node()*">
<
xsl:apply-templates/>
</
xsl:variable>
<
xsl:if test=
"exists($content)">
<
span>
<
xsl:copy-of select=
"@class|@dir|@lang|@title"/>
<
xsl:sequence select=
"$content"/>
</
span>
</
xsl:if>
</
xsl:template>
<
xsl:template match=
"@*|node()">
<
xsl:copy>
<
xsl:apply-templates select=
"@*|node()"/>
</
xsl:copy>
</
xsl:template>
<
xsl:template mode=
"clean" match=
"ol[.. and not(li)]"/>
<
xsl:template mode=
"clean" match=
"@*|node()">
<
xsl:copy>
<
xsl:apply-templates mode=
"#current" select=
"@*|node()"/>
</
xsl:copy>
</
xsl:template>
<
xsl:function name=
"f:is-heading" as=
"xs:boolean">
<
xsl:param name=
"node" as=
"element()"/>
<
xsl:sequence select=
"boolean($node[self::h1 or self::h2 or self::h3 or self::h4 or self::h5 or self::h6 or self::hgroup])"/>
</
xsl:function>
<
xsl:function name=
"f:is-section" as=
"xs:boolean">
<
xsl:param name=
"node" as=
"element()"/>
<
xsl:sequence select=
"boolean($node[self::article or self::aside or self::nav or self::section])"/>
</
xsl:function>
<
xsl:function name=
"f:rank" as=
"xs:integer">
<
xsl:param name=
"node" as=
"element()?"/>
<
xsl:choose>
<
xsl:when test=
"$node[self::h1 or self::h2 or self::h3 or self::h4 or self::h5 or self::h6]">
<
xsl:sequence select=
"7-xs:integer(substring-after(name($node),'h'))"/>
</
xsl:when>
<
xsl:when test=
"$node[self::hgroup]">
<
xsl:sequence select=
"max($node/*/f:rank(.))"/>
</
xsl:when>
<
xsl:otherwise>
<
xsl:sequence select=
"0"/>
</
xsl:otherwise>
</
xsl:choose>
</
xsl:function>
</
xsl:stylesheet>