<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.daisy.org/z3986/2005/dtbook/" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:pfunc="http://www.daisy.org/pipeline/xslt/function" version="2.0" exclude-result-prefixes="xs html pfunc">
<xsl:output method="xml" encoding="UTF-8" indent="yes" doctype-public="-//NISO//DTD dtbook 2005-2//EN" doctype-system="http://www.daisy.org/z3986/2005/dtbook-2005-2.dtd"/>
<xsl:param name="uid" as="xs:string" select="'[UID]'"/>
<xsl:param name="title" as="xs:string" select="'[DTB_TITLE]'"/>
<xsl:param name="cssURI" as="xs:string" select="'[cssURI]'"/>
<xsl:param name="nccURI" as="xs:string" select="'[nccURI]'"/>
<xsl:param name="transferDcMetadata" as="xs:string" select="'false'"/>
<xsl:param name="transformationMode" as="xs:string" select="'standalone'"/>
<xsl:variable name="nccURI.mod" as="xs:string" select="translate($nccURI,'\','/')"/>
<xsl:variable name="cssURI.mod" as="xs:string" select="replace(translate($cssURI,'\','/'),'.*/(.+)','$1')"/>
<xsl:variable name="dtbMigration" as="xs:boolean" select="matches($transformationMode,'DTBmigration','i')"/>
<xsl:variable name="regexpMatchTitle" as="xs:string" select="'^title$|^dc:title$|^dtb:title$'"/>
<xsl:variable name="regexpMatchID" as="xs:string" select="'^id$|^dc:id$|^dtb:id$|^uid$|^dc:uid$|^dtb:uid$|^identifier$|^dc:identifier$|^dtb:identifier$'"/>
<xsl:variable name="regexpMatchTitleAndID" as="xs:string" select="concat($regexpMatchTitle,'|',$regexpMatchID)"/>
<xsl:variable name="smil" as="xs:string" select="'.smil#'"/>
<xsl:variable name="xTitle" as="xs:string">
<xsl:choose>
<xsl:when test="$title eq '' or $title eq '[DTB_TITLE]'">
<xsl:choose>
<xsl:when test="html:html/html:head/html:title">
<xsl:value-of select="html:html/html:head/html:title"/>
</xsl:when>
<xsl:when test="//html:meta[matches(@name,$regexpMatchTitle,'i')]">
<xsl:value-of select="//html:meta[matches(@name,$regexpMatchTitle,'i')][1]/@content"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="''"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$title"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="xUID" as="xs:string">
<xsl:choose>
<xsl:when test="$uid eq '' or $uid eq '[UID]'">
<xsl:choose>
<xsl:when test="//html:meta[matches(@name,$regexpMatchID,'i')]">
<xsl:value-of select="//html:meta[matches(@name,$regexpMatchID,'i')][1]/@content"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="''"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$uid"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:template match="/">
<xsl:if test="$cssURI ne '[cssURI]' and $cssURI.mod ne ''">
<xsl:processing-instruction name="xml-stylesheet">
<xsl:text> type="text/css" href="</xsl:text>
<xsl:value-of select="$cssURI.mod"/>
<xsl:text>"</xsl:text>
</xsl:processing-instruction>
</xsl:if>
<dtbook version="2005-2">
<xsl:copy-of select="html:html/@xml:lang"/>
<xsl:apply-templates/>
</dtbook>
</xsl:template>
<xsl:template match="html:head">
<head>
<meta name="dtb:uid" content="{$xUID}"/>
<meta name="dc:Title" content="{$xTitle}"/>
<xsl:choose>
<xsl:when test=" $dtbMigration and matches($transferDcMetadata,'true','i') and doc-available($nccURI.mod) and $nccURI ne '[nccURI]'">
<xsl:apply-templates select=" doc($nccURI.mod)//html:head/html:meta[ starts-with(@name,'dc:') and not( matches( @name, concat( $regexpMatchTitleAndID, '|^dc:format$' ), 'i' ) ) ]" mode="metadata-from-ncc"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="html:meta[not(matches(@name,$regexpMatchTitleAndID,'i'))]"/>
</xsl:otherwise>
</xsl:choose>
</head>
</xsl:template>
<xsl:template match="html:meta[@http-equiv]" priority="10"/>
<xsl:template match="html:meta[@name]">
<meta>
<xsl:attribute name="name">
<xsl:choose>
<xsl:when test="matches(@name,'^dc:(creator|subject|description|publisher|contributor|date|type|format|source|language|relation|coverage|rights)$','i')">
<xsl:value-of select="concat('dc:',pfunc:initialCaps(substring-after(@name,'dc:')))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:copy-of select="@content, @scheme"/>
</meta>
</xsl:template>
<xsl:template match="html:meta[not(@name)]">
<meta>
<xsl:copy-of select="@name, @content, @scheme"/>
</meta>
</xsl:template>
<xsl:template match="html:meta" mode="metadata-from-ncc">
<xsl:if test="matches(@name,'^dc:(creator|subject|description|publisher|contributor|date|type|source|language|relation|coverage|rights)$','i')">
<meta>
<xsl:attribute name="name" select="concat('dc:',pfunc:initialCaps(substring-after(@name,'dc:')))"/>
<xsl:copy-of select="@content, @scheme, @http-equiv"/>
</meta>
</xsl:if>
</xsl:template>
<xsl:template match="html:link">
<link rel="stylesheet" type="text/css" href="{concat('dtbook_',@href)}"/>
</xsl:template>
<xsl:template match="html:body">
<book>
<xsl:call-template name="copy-attributes"/>
<xsl:if test="html:h1[@class eq 'frontmatter'] or //html:head/html:title">
<frontmatter>
<xsl:apply-templates select="//html:head/html:title"/>
<xsl:apply-templates select="html:h1[@class eq 'frontmatter']"/>
</frontmatter>
</xsl:if>
<bodymatter>
<xsl:apply-templates select="html:h1[not(@class eq 'frontmatter' or @class eq 'rearmatter')]"/>
</bodymatter>
<xsl:if test="html:h1[@class eq 'rearmatter']">
<rearmatter>
<xsl:apply-templates select="html:h1[@class eq 'rearmatter']"/>
</rearmatter>
</xsl:if>
</book>
</xsl:template>
<xsl:template match="html:title">
<doctitle>
<xsl:apply-templates/>
</doctitle>
</xsl:template>
<xsl:template match="element()[matches(local-name(),'^h[1-6]$')]">
<xsl:variable name="h.this.name" as="xs:string" select="local-name()"/>
<xsl:variable name="h.this.level" as="xs:integer" select="xs:integer(substring-after($h.this.name,'h'))"/>
<xsl:variable name="h.next" select="following-sibling::*[matches(local-name(),'^h[1-6]$')][1]"/>
<xsl:variable name="h.next.name" select="local-name($h.next)"/>
<xsl:variable name="e.up-to-next-heading" select=" if ($h.next) then following-sibling::*[. << $h.next] else following-sibling::*"/>
<xsl:variable name="h.next-on-same-level-or-higher" select="following-sibling::*[matches(local-name(),concat('^h[1-',string($h.this.level),']$'))][1]"/>
<xsl:variable name="h.next-level.all" select="following-sibling::*[matches(local-name(),concat('^h',string($h.this.level + 1),'$'))]"/>
<xsl:variable name="h.next-level.relevant" select=" if ($h.next-on-same-level-or-higher) then $h.next-level.all[. << $h.next-on-same-level-or-higher] else $h.next-level.all"/>
<xsl:variable name="NoRelevantElementsUntilNextHeading" as="xs:boolean" select="every $e in $e.up-to-next-heading satisfies matches(local-name($e),'^br$|^hr$')"/>
<xsl:variable name="NextFollowingSiblingIsHeadingOnLowerLevel" as="xs:boolean" select="matches(local-name(following-sibling::*[not(matches(local-name(.),'^br$|^hr$'))][1]),concat('^h[',string($h.this.level+1),'-6]$'))"/>
<xsl:element name="{concat('level',string($h.this.level))}">
<xsl:copy-of select="@class"/>
<xsl:element name="{local-name()}">
<xsl:call-template name="copy-heading-attributes"/>
<xsl:apply-templates/>
</xsl:element>
<xsl:apply-templates select="$e.up-to-next-heading"/>
<xsl:if test="$NoRelevantElementsUntilNextHeading and not($NextFollowingSiblingIsHeadingOnLowerLevel)">
<p class="dummy"/>
</xsl:if>
<xsl:apply-templates select="$h.next-level.relevant"/>
</xsl:element>
</xsl:template>
<xsl:template match="html:span[starts-with(@class,'page-')]">
<pagenum page="{substring-after(@class,'page-')}" id="{if (@id) then @id else concat('page-',normalize-space(.))}">
<xsl:call-template name="copy-page-attributes"/>
<xsl:value-of select="normalize-space(.)"/>
</pagenum>
</xsl:template>
<xsl:template match="html:span[@class eq 'sentence']">
<xsl:variable name="e.next" select="following-sibling::*[1]"/>
<sent>
<xsl:call-template name="copy-span-attributes"/>
<xsl:apply-templates/>
</sent>
</xsl:template>
<xsl:template match="html:span[ends-with(@class,'-prodnote')]">
<xsl:variable name="e.p.1" select="preceding-sibling::*[1]"/>
<xsl:variable name="e.p.2" select="preceding-sibling::*[2]"/>
<xsl:variable name="part-of-imggroup" as="xs:boolean" select=" local-name($e.p.1) eq 'img' or ( local-name($e.p.1) eq 'span' and $e.p.1/@class eq 'caption' and local-name($e.p.2) eq 'img' )"/>
<xsl:choose>
<xsl:when test="$part-of-imggroup"/>
<xsl:otherwise>
<prodnote render="{substring-before(@class,'-prodnote')}">
<xsl:call-template name="copy-span-attributes"/>
<xsl:apply-templates/>
</prodnote>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="html:span[ends-with(@class,'-prodnote')]" mode="inside-imgrp">
<xsl:param name="group-id" as="xs:string"/>
<prodnote render="{substring-before(@class,'-prodnote')}" imgref="{concat('img-',$group-id)}" id="{concat('pnote-',$group-id)}">
<xsl:call-template name="copy-std-attr"/>
<xsl:apply-templates/>
</prodnote>
</xsl:template>
<xsl:template match="html:span[@class eq 'caption']">
<xsl:variable name="e.p.1" select="preceding-sibling::*[1]"/>
<xsl:variable name="e.p.2" select="preceding-sibling::*[2]"/>
<xsl:variable name="part-of-imggroup" as="xs:boolean" select=" local-name($e.p.1) eq 'img' or ( local-name($e.p.1) eq 'span' and ends-with($e.p.1/@class,'-prodnote') and local-name($e.p.2) eq 'img' )"/>
<xsl:choose>
<xsl:when test="$part-of-imggroup"/>
<xsl:otherwise>
<xsl:next-match/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="html:span[@class eq 'caption']" mode="inside-imgrp">
<xsl:param name="group-id" as="xs:string"/>
<caption imgref="{concat('img-',$group-id)}" id="{concat('caption-',$group-id)}">
<xsl:call-template name="copy-std-attr"/>
<xsl:apply-templates/>
</caption>
</xsl:template>
<xsl:template match="html:body/html:span[@class eq 'noteref']" priority="5">
<p class="noteref">
<xsl:next-match/>
</p>
</xsl:template>
<xsl:template match="html:span[@class eq 'noteref']" priority="3">
<noteref>
<xsl:attribute name="idref" select="@bodyref (: if (contains(@bodyref,'#')) then substring-after(@bodyref,'#') else @bodyref :)"/>
<xsl:copy-of select="@id"/>
<xsl:call-template name="copy-std-attr"/>
<xsl:apply-templates/>
</noteref>
</xsl:template>
<xsl:template match="html:a[contains(@href,$smil)]">
<xsl:choose>
<xsl:when test="$dtbMigration">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<xsl:next-match/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="html:div[@class eq 'notebody']">
<note>
<xsl:copy-of select="@id"/>
<xsl:call-template name="copy-std-attr"/>
<xsl:apply-templates/>
</note>
</xsl:template>
<xsl:template match="html:img">
<xsl:variable name="e.f.1" select="following-sibling::*[1]"/>
<xsl:variable name="e.f.2" select="following-sibling::*[2]"/>
<xsl:variable name="imggrp.associate.first" as="xs:boolean" select=" local-name($e.f.1) eq 'span' and ends-with($e.f.1/@class,'-prodnote') or local-name($e.f.1) eq 'span' and $e.f.1/@class eq 'caption' "/>
<xsl:variable name="imggrp.associate.second" as="xs:boolean" select=" ( local-name($e.f.1) eq 'span' and ends-with($e.f.1/@class,'-prodnote') and local-name($e.f.2) eq 'span' and $e.f.2/@class eq 'caption' ) or ( local-name($e.f.2) eq 'span' and ends-with($e.f.2/@class,'-prodnote') and local-name($e.f.1) eq 'span' and $e.f.1/@class eq 'caption' ) "/>
<xsl:choose>
<xsl:when test="$imggrp.associate.first">
<xsl:variable name="id" as="xs:string" select="generate-id()"/>
<imggroup id="{concat('imggrp-',$id)}">
<img>
<xsl:copy-of select="@src, @alt"/>
<xsl:call-template name="copy-attributes-not-id"/>
<xsl:attribute name="id" select="concat('img-',$id)"/>
</img>
<xsl:apply-templates select="$e.f.1" mode="inside-imgrp">
<xsl:with-param name="group-id" as="xs:string" select="$id"/>
</xsl:apply-templates>
<xsl:if test="$imggrp.associate.second">
<xsl:apply-templates select="$e.f.2" mode="inside-imgrp">
<xsl:with-param name="group-id" as="xs:string" select="$id"/>
</xsl:apply-templates>
</xsl:if>
</imggroup>
</xsl:when>
<xsl:otherwise>
<img>
<xsl:copy-of select="@src, @alt"/>
<xsl:call-template name="copy-attributes"/>
</img>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="html:ol | html:ul">
<list type="{local-name()}">
<xsl:call-template name="copy-attributes"/>
<xsl:apply-templates/>
</list>
</xsl:template>
<xsl:template match="html:a | html:p | html:li | html:dl | html:dt | html:dd | html:span | html:strong | html:em | html:sub | html:sup | html:br | html:div | html:blockquote | html:abbr">
<xsl:element name="{local-name()}">
<xsl:call-template name="copy-attributes"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="html:div[html:span]">
<div>
<xsl:call-template name="copy-attributes"/>
<p class="inserted-by-transformer">
<xsl:apply-templates/>
</p>
</div>
</xsl:template>
<xsl:template match="html:body/html:br">
</xsl:template>
<xsl:template match="html:table | html:table/html:caption | html:tr | html:td | html:th | html:col">
<xsl:element name="{local-name()}">
<xsl:call-template name="copy-table-attributes"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template name="copy-attributes">
<xsl:copy-of select="@id, @class, @href"/>
<xsl:call-template name="copy-std-attr"/>
</xsl:template>
<xsl:template name="copy-attributes-not-id">
<xsl:copy-of select="@class, @href"/>
<xsl:call-template name="copy-std-attr"/>
</xsl:template>
<xsl:template name="copy-heading-attributes">
<xsl:copy-of select="@id"/>
<xsl:call-template name="copy-std-attr"/>
</xsl:template>
<xsl:template name="copy-table-attributes">
<xsl:copy-of select="@id, @rowspan, @colspan, @class, @valign"/>
<xsl:call-template name="copy-std-attr"/>
</xsl:template>
<xsl:template name="copy-span-attributes">
<xsl:copy-of select="@id"/>
<xsl:call-template name="copy-std-attr"/>
</xsl:template>
<xsl:template name="copy-page-attributes">
<xsl:call-template name="copy-std-attr"/>
</xsl:template>
<xsl:template name="copy-std-attr">
<xsl:copy-of select="@title, @dir, @xml:lang"/>
<xsl:call-template name="smilref"/>
</xsl:template>
<xsl:template name="smilref">
<xsl:if test="$dtbMigration and contains(html:a[1]/@href,$smil)">
<xsl:attribute name="smilref" select="html:a[1]/@href"/>
</xsl:if>
</xsl:template>
<xsl:template match="*">
<xsl:if test="local-name() ne 'html'">
<xsl:text>
</xsl:text>
<xsl:comment> **** No template for element: <xsl:value-of select="local-name()"/> **** </xsl:comment>
</xsl:if>
<xsl:apply-templates/>
</xsl:template>
<xsl:function name="pfunc:initialCaps" as="xs:string">
<xsl:param name="string" as="xs:string"/>
<xsl:choose>
<xsl:when test="boolean($string)">
<xsl:value-of select="string-join( ( upper-case(substring($string,1,1)), substring($string,2) ), '' ) "/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
</xsl:stylesheet>