<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:css="http://www.daisy.org/ns/pipeline/braille-css" xmlns:s="org.daisy.pipeline.braille.css.xpath.Style" xmlns:c="http://www.w3.org/ns/xproc-step" exclude-result-prefixes="#all" version="3.0"> <xsl:param name="attribute-name" required="yes"/> <xsl:include href="library.xsl"/> <xsl:template match="/"> <xsl:apply-templates select="/*"/> <xsl:result-document href="irrelevant"> <c:result content-type="text/plain"> <xsl:variable name="id-to-style" as="map(xs:string,xs:string)"> <xsl:map> <xsl:for-each select="//*/@*[local-name()=$attribute-name and namespace-uri()='']"> <xsl:variable name="id" select="(parent::*/@id/string(.),parent::*/@xml:id/string(.),parent::*/generate-id(.))[1]"/> <xsl:map-entry key="$id" select="string(.)"/> </xsl:for-each> </xsl:map> </xsl:variable> <xsl:variable name="selector-to-style" as="map(xs:string,item())"> <xsl:iterate select="map:keys($id-to-style)"> <xsl:param name="styles" as="map(xs:string,item())" select="map{}"/> <xsl:param name="selectors" as="map(xs:string,xs:string*)" select="map{}"/> <xsl:on-completion> <xsl:map> <xsl:for-each select="map:keys($styles)"> <xsl:variable name="style" as="item()" select="map:get($styles,.)"/> <xsl:variable name="selectors" as="xs:string*" select="map:get($selectors,.)"/> <xsl:map-entry key="string-join($selectors,', ')" select="$style"/> </xsl:for-each> </xsl:map> </xsl:on-completion> <xsl:variable name="selector" as="xs:string" select="concat('#',.)"/> <xsl:variable name="style" as="xs:string" select="map:get($id-to-style,.)"/> <xsl:variable name="selectors" as="map(xs:string,xs:string*)" select="map:put($selectors,$style,(map:get($selectors,$style),$selector))"/> <xsl:choose> <xsl:when test="map:contains($styles,$style)"> <xsl:next-iteration> <xsl:with-param name="selectors" select="$selectors"/> </xsl:next-iteration> </xsl:when> <xsl:otherwise> <xsl:variable name="serialized" as="xs:string" select="$style"/> <xsl:variable name="style" as="item()?" select="css:parse-stylesheet($style)"/> <xsl:choose> <xsl:when test="empty($style)"> <xsl:next-iteration> <xsl:with-param name="selectors" select="$selectors"/> </xsl:next-iteration> </xsl:when> <xsl:otherwise> <xsl:next-iteration> <xsl:with-param name="styles" select="map:put($styles,$serialized,$style)"/> <xsl:with-param name="selectors" select="$selectors"/> </xsl:next-iteration> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:iterate> </xsl:variable> <xsl:variable name="page-styles" as="map(xs:string,item())"> <xsl:map> <xsl:for-each select="map:keys($selector-to-style)"> <xsl:variable name="style" as="item()" select="map:get($selector-to-style,.)"/> <xsl:call-template name="extract-page-styles"> <xsl:with-param name="style" select="$style"/> </xsl:call-template> </xsl:for-each> </xsl:map> </xsl:variable> <xsl:variable name="page-style-names" as="map(xs:string,xs:string)"> <xsl:map> <xsl:for-each select="map:keys($page-styles)"> <xsl:variable name="style" as="xs:string" select="."/> <xsl:variable name="name" as="xs:string" select="concat('page-',position())"/> <xsl:map-entry key="$style" select="$name"/> </xsl:for-each> </xsl:map> </xsl:variable> <xsl:variable name="style" as="item()*"> <xsl:for-each select="map:keys($page-styles)"> <xsl:sequence select="s:of(concat('@page ',map:get($page-style-names,.)), map:get($page-styles,.))"/> </xsl:for-each> <xsl:for-each select="map:keys($selector-to-style)"> <xsl:variable name="style" as="item()"> <xsl:call-template name="substitute-named-pages"> <xsl:with-param name="style" select="map:get($selector-to-style,.)"/> <xsl:with-param name="page-style-names" tunnel="yes" select="$page-style-names"/> </xsl:call-template> </xsl:variable> <xsl:sequence select="s:of(.,$style)"/> </xsl:for-each> </xsl:variable> <xsl:value-of select="css:serialize-stylesheet-pretty($style,' ')"/> <xsl:text> </xsl:text> </c:result> </xsl:result-document> </xsl:template> <xsl:template name="extract-page-styles" as="map(xs:string,item())"> <xsl:param name="style" as="item()" required="true"/> <xsl:map> <xsl:for-each select="s:iterate($style)"> <xsl:variable name="selector" as="xs:string?" select="s:selector(.)"/> <xsl:if test="$selector"> <xsl:variable name="style" as="item()" select="s:get(.,$selector)"/> <xsl:choose> <xsl:when test="$selector='@page'"> <xsl:variable name="serialized" as="xs:string" select="string(.)"/> <xsl:map-entry key="$serialized" select="$style"/> </xsl:when> <xsl:otherwise> <xsl:call-template name="extract-page-styles"> <xsl:with-param name="style" select="$style"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:if> </xsl:for-each> </xsl:map> </xsl:template> <xsl:template name="substitute-named-pages" as="item()"> <xsl:param name="style" as="item()" required="true"/> <xsl:param name="page-style-names" tunnel="yes" as="map(xs:string,xs:string)" required="true"/> <xsl:variable name="style" as="item()*"> <xsl:for-each select="s:iterate($style)"> <xsl:variable name="selector" as="xs:string?" select="s:selector(.)"/> <xsl:choose> <xsl:when test="$selector"> <xsl:choose> <xsl:when test="$selector='@page'"> <xsl:variable name="serialized" as="xs:string" select="string(.)"/> <xsl:sequence select="css:parse-stylesheet(concat('page: ',map:get($page-style-names,$serialized)))"/> </xsl:when> <xsl:otherwise> <xsl:variable name="style" as="item()"> <xsl:call-template name="substitute-named-pages"> <xsl:with-param name="style" select="s:get(.,$selector)"/> </xsl:call-template> </xsl:variable> <xsl:sequence select="s:of($selector,$style)"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:sequence select="."/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:variable> <xsl:sequence select="s:merge($style)"/> </xsl:template> <xsl:template match="*[not(@id)][@*[local-name()=$attribute-name and namespace-uri()='']]"> <xsl:copy> <xsl:attribute name="id" select="(@xml:id/string(.),generate-id(.))[1]"/> <xsl:apply-templates mode="#current" select="@* except @xml:id"/> <xsl:apply-templates mode="#current"/> </xsl:copy> </xsl:template> <xsl:template match="@*|node()" mode="#default substitute-named-pages"> <xsl:copy> <xsl:apply-templates mode="#current" select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>