<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:pf="http://www.daisy.org/ns/pipeline/functions" xmlns:f="http://www.daisy.org/ns/pipeline/internal-functions" xmlns:d="http://www.daisy.org/ns/pipeline/data" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:m="http://www.w3.org/1998/Math/MathML" 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:import href="http://www.daisy.org/pipeline/modules/html-utils/library.xsl"/> <xsl:output indent="yes"/> <xsl:variable name="fileset" select="collection()[/d:fileset][1]" as="document-node()?"/> <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="node() | @*"/> </xsl:copy> </xsl:template> <xsl:template match="head"> <xsl:copy> <xsl:apply-templates select="node() | @*"/> <xsl:if test="(//@aria-describedat|//@longdesc) [pf:is-relative(.) and not(starts-with(.,'#')) and pf:get-extension(f:clean-uri(.,false()))=('xhtml','html','htm')]"> <style> <xsl:sequence select="concat( ' .dp2-invisible { ', ' position: absolute !important; ', ' height: 1px; width: 1px; ', ' overflow: hidden; ', ' clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ ', ' clip: rect(1px, 1px, 1px, 1px); ', '} ' )"/> </style> </xsl:if> </xsl:copy> </xsl:template> <xsl:template match="body"> <xsl:copy> <xsl:apply-templates select="node() | @*"/> <xsl:apply-templates select="//@aria-describedat|//@longdesc" mode="iframe"/> </xsl:copy> </xsl:template> <xsl:template match="@longdesc[starts-with(.,'#')] |@aria-describedat[starts-with(.,'#')]" priority="2"> <xsl:attribute name="aria-describedby" select="substring-after(.,'#')"/> </xsl:template> <xsl:key name="desc" match="@aria-describedat|@longdesc" use="f:clean-uri(.,false())"/> <xsl:template match="@longdesc[pf:is-relative(.)][../empty(@aria-describedat|@aria-describedby)]"> <xsl:variable name="desc-uri" select="f:clean-uri(.)"/> <xsl:variable name="desc-path" select="replace($desc-uri,'([^#]+)(#.*)?','$1')"/> <xsl:if test="$desc-uri"> <xsl:attribute name="longdesc" select="f:clean-uri(.)"/> </xsl:if> <xsl:if test="pf:get-extension($desc-path)=('xhtml','html','htm')"> <xsl:attribute name="aria-describedby" select="generate-id(key('desc',$desc-path)[1])"/> </xsl:if> </xsl:template> <xsl:template match="@aria-describedat[pf:is-absolute(.)]"> <xsl:attribute name="longdesc" select="."/> <xsl:attribute name="aria-describedby" select="generate-id(.)"/> </xsl:template> <xsl:template match="@aria-describedat"> <xsl:variable name="desc-path" select="f:clean-uri(.,false())"/> <xsl:choose> <xsl:when test="not($desc-path)"/> <xsl:when test="pf:get-extension($desc-path)=('xhtml','html','htm')"> <xsl:attribute name="aria-describedby" select="generate-id(key('desc',$desc-path)[1])"/> </xsl:when> <xsl:otherwise> <xsl:attribute name="aria-describedat" select="."/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="@aria-describedat[pf:is-absolute(.)]" mode="iframe"> <aside class="dp2-invisible"> <iframe id="{generate-id(.)}" src="{.}"/> </aside> </xsl:template> <xsl:template match="@aria-describedat[pf:is-relative(.) and not(starts-with(.,'#'))] |@longdesc[not(starts-with(.,'#')) and not(../(@aria-describedat|@aria-describedby))]" mode="iframe"> <xsl:variable name="desc-path" select="f:clean-uri(.,false())"/> <xsl:variable name="is-html" as="xs:boolean" select="pf:get-extension($desc-path)=('xhtml','html','htm')"/> <xsl:if test="$is-html and key('desc',$desc-path)[1] is ."> <aside class="dp2-invisible"> <iframe id="{generate-id(.)}" src="{f:clean-uri(.)}"/> </aside> </xsl:if> </xsl:template> <xsl:template match="@longdesc|@aria-describedat" mode="iframe"/> <xsl:template match="link"> <xsl:variable name="rel" as="xs:string*" select="tokenize(@rel,'\s+')"/> <xsl:choose> <xsl:when test="$rel='stylesheet' and not(@type='text/css' or pf:get-extension(@href)='css')"> <xsl:message select="concat('[WARNING] Discarding stylesheet ''',@href,''' of non-core type.')"/> </xsl:when> <xsl:when test="$rel='pronunciation' and not(@type='application/pls+xml' or pf:get-extension(@href)='pls')"> <xsl:message select="concat('[WARNING] Discarding pronunciation lexicon ''',@href,''' of non-core type.')"/> </xsl:when> <xsl:when test="pf:is-relative(@href) and not($rel=('stylesheet','pronunciation'))"> <xsl:message select="concat('[WARNING] Discarding local link ''',@href,''' of unsupported relation type ''',@rel,'''.')"/> </xsl:when> <xsl:otherwise> <xsl:sequence select="f:copy-if-clean(@href)"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="script"> <xsl:choose> <xsl:when test="@src and not(normalize-space(@type)=('','text/javascript','text/ecmascript', 'text/javascript1.0','text/javascript1.1','text/javascript1.2','text/javascript1.3', 'text/javascript1.4','text/javascript1.5','text/jscript','text/livescript', 'text/x-javascript','text/x-ecmascript','application/x-javascript', 'application/x-ecmascript','application/javascript','application/ecmascript'))"> <xsl:message select="'[WARNING] Discarding script of non-core type.'"/> </xsl:when> <xsl:when test="@src"> <xsl:sequence select="f:copy-if-clean(@src)"/> </xsl:when> <xsl:otherwise> <script type="{if (normalize-space(@type)=('','text/javascript','text/ecmascript', 'text/javascript1.0','text/javascript1.1','text/javascript1.2','text/javascript1.3', 'text/javascript1.4','text/javascript1.5','text/jscript','text/livescript', 'text/x-javascript','text/x-ecmascript','application/x-javascript', 'application/x-ecmascript','application/javascript','application/ecmascript')) then 'text/javascript' else @type}"> <xsl:copy-of select="@* except @type | node()"/> </script> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="a[@href]"> <xsl:choose> <xsl:when test="pf:get-scheme(@href)='mailto' or pf:is-absolute(@href)"> <xsl:copy> <xsl:apply-templates select="@* except (@target|@rel|@media|@targetlang|@type) | node()"/> </xsl:copy> </xsl:when> <xsl:otherwise> <xsl:sequence select="f:copy-if-clean(@href,(),(@target|@rel|@media|@targetlang|@type))"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="img[@src]"> <xsl:choose> <xsl:when test="pf:get-scheme(@src)='data'"> <xsl:copy-of select="."/> </xsl:when> <xsl:when test="pf:is-absolute(@src)"> <xsl:message select="concat('[WARNING] Replacing remote image ''',@src,''' by alternative text.')"/> <span> <xsl:copy-of select="@* except (@alt|@src|@crossorigin|@usemap|@ismap|@width|@height)"/> <xsl:value-of select="@alt"/> </span> </xsl:when> <xsl:when test="not(pf:get-extension(@src)=('png','jpeg','jpg','gif','svg'))"> <xsl:message select="concat('[WARNING] The type of image ''',@src,''' is not a core EPUB media type. Replacing by alternative text.')"/> <span> <xsl:copy-of select="@* except (@alt|@src|@crossorigin|@usemap|@ismap|@width|@height)"/> <xsl:value-of select="@alt"/> </span> </xsl:when> <xsl:otherwise> <xsl:sequence select="f:copy-if-clean(@src)"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="iframe[@src]"> <xsl:choose> <xsl:when test="pf:is-absolute(@src)"> <xsl:message select="concat('[WARNING] Discarding remote iframe ''',@src,'''.')"/> </xsl:when> <xsl:otherwise> <xsl:sequence select="f:copy-if-clean(@src)"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="embed[@src]"> <xsl:choose> <xsl:when test="pf:is-absolute(@src)"> <xsl:message select="concat('[WARNING] Discarding remote embedded resource ''',@src,'''.')"/> </xsl:when> <xsl:when test="f:is-core-audio(@src,@type)"> <xsl:sequence select="f:copy-if-clean(@src,'audio',(@type,@width,@height))"/> </xsl:when> <xsl:when test="f:is-core-image(@src,@type)"> <xsl:sequence select="f:copy-if-clean(@src,'img',(@type))"/> </xsl:when> <xsl:otherwise> <xsl:message select="concat('[WARNING] Discarding embedded resource of non-core type ''',@src,'''.')"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="object[@data]"> <xsl:choose> <xsl:when test="pf:is-absolute(@data)"> <xsl:message select="concat('[WARNING] Discarding remote object ''',@data,'''.')"/> </xsl:when> <xsl:when test="f:is-core-audio(@data,@type) or f:is-core-image(@data,@type) or exists(* except param)"> <xsl:sequence select="f:copy-if-clean(@data)"/> </xsl:when> <xsl:otherwise> <xsl:message select="concat('[WARNING] Discarding object ''',@data,''' of non-core type with no fallback.')"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="audio[@src]"> <xsl:choose> <xsl:when test="f:is-core-audio(@src,()) or exists(* except track) or normalize-space(.)"> <xsl:sequence select="f:copy-if-clean(@src)"/> </xsl:when> <xsl:otherwise> <xsl:message select="concat('[WARNING] Discarding audio resource ''',@src,''' of non-core type with no fallback.')"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="audio[source]"> <xsl:choose> <xsl:when test="exists(source[f:is-core-audio(@src,@type)]) or exists(* except (source,track)) or normalize-space(.)"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:when> <xsl:otherwise> <xsl:message select="'[WARNING] Discarding audio resource with no fallback.'"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="video[@src]"> <xsl:choose> <xsl:when test="exists(* except track) or normalize-space(.)"> <xsl:sequence select="f:copy-if-clean(@src)"/> </xsl:when> <xsl:otherwise> <xsl:message select="concat('[WARNING] Discarding video resource ''',@src,''' of non-core type with no fallback.')"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="video[source]"> <xsl:choose> <xsl:when test="exists(* except (source,track)) or normalize-space(.)"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:when> <xsl:otherwise> <xsl:message select="'[WARNING] Discarding video resource with no fallback.'"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="source"> <xsl:sequence select="f:copy-if-clean(@src)"/> </xsl:template> <xsl:template match="track"> <xsl:sequence select="f:copy-if-clean(@src)"/> </xsl:template> <xsl:template match="svg:animate|svg:set|svg:animateMotion|svg:animatecolor"> <xsl:message select="'[WARNING] Discarding SVG animation element.'"/> </xsl:template> <xsl:template match="svg:audio"> <xsl:message select="'[WARNING] Discarding SVG ''audio'' element, not part of SVG 1.1'"/> </xsl:template> <xsl:template match="svg:foreignObject[@xlink:href]"> <xsl:message select="'[WARNING] Discarding SVG ''foreignObject'' element with external reference, not part of SVG 1.1'"/> </xsl:template> <xsl:template match="svg:foreignObject/@requiredExtensions"> <xsl:attribute name="requiredExtensions" select="'http://www.idpf.org/2007/ops'"/> </xsl:template> <xsl:template match="svg:font-face-uri"> <xsl:sequence select="f:copy-if-clean(@xlink:href)"/> </xsl:template> <xsl:template match="svg:handler"> <xsl:message select="'[WARNING] Discarding SVG ''handler'' element, not part of SVG 1.1'"/> </xsl:template> <xsl:template match="svg:image"> <xsl:sequence select="f:copy-if-clean(@xlink:href)"/> </xsl:template> <xsl:template match="svg:script[@xlink:href]"/> <xsl:template match="svg:video"> <xsl:message select="'[WARNING] Discarding SVG ''video'' element, not part of SVG 1.1'"/> </xsl:template> <xsl:template match="m:math[@altimg]"> <xsl:variable name="clean-uri" select="f:clean-uri(@altimg)"/> <xsl:choose> <xsl:when test="$clean-uri"> <m:math altimg="{f:clean-uri(@altimg)}"> <xsl:apply-templates select="@* except @altimg | node()"/> </m:math> </xsl:when> <xsl:otherwise> <xsl:message select="concat('[WARNING] Discarding missing math/@altimg ''',@altimg,'''.')"/> <m:math> <xsl:apply-templates select="@* except @altimg | node()"/> </m:math> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="m:mglyph[@src]"> <xsl:sequence select="f:copy-if-clean(@src)"/> </xsl:template> <xsl:function name="f:is-core-image" as="xs:boolean"> <xsl:param name="uri" as="item()?"/> <xsl:param name="type" as="item()?"/> <xsl:sequence select="$type=('image/gif','image/jpeg','image/png','image/svg+xml') or pf:get-extension($uri)=('gif','jpeg','jpg','png','svg')"/> </xsl:function> <xsl:function name="f:is-core-audio" as="xs:boolean"> <xsl:param name="uri" as="item()?"/> <xsl:param name="type" as="item()?"/> <xsl:sequence select="$type=('audio/mpeg','audio/mp4') or pf:get-extension($uri)=('mp3','m4a','aac')"/> </xsl:function> <xsl:function name="f:clean-uri" as="xs:string?"> <xsl:param name="uri" as="attribute()?"/> <xsl:sequence select="f:clean-uri($uri,true())"/> </xsl:function> <xsl:function name="f:clean-uri" as="xs:string?"> <xsl:param name="uri" as="attribute()?"/> <xsl:param name="fragment" as="xs:boolean?"/> <xsl:variable name="resolved" select="resolve-uri(pf:normalize-uri($uri,false()),pf:html-base-uri($uri))"/> <xsl:if test="$fileset/d:fileset/d:file[resolve-uri(@href,base-uri(.))=$resolved]"> <xsl:sequence select="$uri"/> </xsl:if> </xsl:function> <xsl:function name="f:copy-if-clean"> <xsl:param name="att" as="attribute()?"/> <xsl:sequence select="f:copy-if-clean($att,(),())"/> </xsl:function> <xsl:function name="f:copy-if-clean"> <xsl:param name="att" as="attribute()?"/> <xsl:param name="elm-name" as="xs:string?"/> <xsl:param name="skip-att" as="attribute()*"/> <xsl:variable name="elm" as="element()?" select="$att/.."/> <xsl:variable name="clean-uri" as="xs:string?" select="f:clean-uri($att)"/> <xsl:choose> <xsl:when test="$clean-uri"> <xsl:element name="{if($elm-name) then $elm-name else $elm/local-name()}" namespace="{if ($elm-name) then 'http://www.w3.org/1999/xhtml' else $elm/namespace-uri()}"> <xsl:attribute name="{$att/local-name()}" namespace="{$att/namespace-uri()}" select="$clean-uri"/> <xsl:apply-templates select="$elm/@* except ($att,$skip-att)"/> <xsl:apply-templates select="$elm/node()"/> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:message select="concat('[WARNING] Discarding missing ',$elm/name(),' ''',$att,'''.')"/> <xsl:apply-templates select="$elm/node()"/> </xsl:otherwise> </xsl:choose> </xsl:function> </xsl:stylesheet>