<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" version="2.0" exclude-result-prefixes="#all"> <xsl:key name="ids" match="*[@id]" use="@id"/> <xsl:template name="f:generate-ids" as="xs:string*"> <xsl:param name="amount" as="xs:integer" required="yes"/> <xsl:param name="prefix" as="xs:string" required="yes"/> <xsl:param name="in-use" select="()"/> <xsl:param name="_feed" as="xs:integer" select="1"/> <xsl:variable name="ids" as="xs:string*" select="for $i in 1 to $amount return concat($prefix,$_feed + $i - 1)"/> <xsl:variable name="in-use" as="document-node()"> <xsl:choose> <xsl:when test="$in-use instance of document-node()"> <xsl:sequence select="$in-use"/> </xsl:when> <xsl:otherwise> <xsl:document> <d:ids> <xsl:for-each select="$in-use"> <d:id id="{.}"/> </xsl:for-each> </d:ids> </xsl:document> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="ids" as="xs:string*" select="$ids[empty(key('ids',.,$in-use))]"/> <xsl:sequence select="$ids"/> <xsl:if test="count($ids) < $amount"> <xsl:call-template name="f:generate-ids"> <xsl:with-param name="amount" select="$amount - count($ids)"/> <xsl:with-param name="prefix" select="$prefix"/> <xsl:with-param name="in-use" select="$in-use"/> <xsl:with-param name="_feed" select="$_feed + $amount"/> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template name="pf:next-match-with-generated-ids"> <xsl:param name="prefix" as="xs:string" required="yes"/> <xsl:param name="for-elements" as="element()*" select=".//*"/> <xsl:param name="in-use" as="xs:string*" select="root()//@id"/> <xsl:variable name="ids" as="xs:string*"> <xsl:call-template name="f:generate-ids"> <xsl:with-param name="amount" select="count($for-elements)"/> <xsl:with-param name="prefix" select="$prefix"/> <xsl:with-param name="in-use" select="$in-use"/> </xsl:call-template> </xsl:variable> <xsl:variable name="idmap"> <xsl:document> <d:idmap> <xsl:for-each select="$for-elements"> <xsl:variable name="i" select="position()"/> <d:id element="{generate-id(.)}" id="{$ids[$i]}"/> </xsl:for-each> </d:idmap> </xsl:document> </xsl:variable> <xsl:next-match> <xsl:with-param name="f:generated-ids" tunnel="yes" select="$idmap"/> </xsl:next-match> </xsl:template> <xsl:key name="f:element" match="d:id" use="string(@element)"/> <xsl:template name="pf:generate-id" as="attribute(id)"> <xsl:param name="f:generated-ids" tunnel="yes" select="()"/> <xsl:if test="not(exists($f:generated-ids))"> <xsl:message terminate="yes" select="'pf:generate-id must be called from within pf:next-match-with-generated-ids.'"/> </xsl:if> <xsl:variable name="element-id" as="xs:string" select="generate-id(.)"/> <xsl:variable name="id" as="attribute()?" select="key('f:element',$element-id,$f:generated-ids)[1]/@id"/> <xsl:if test="not(exists($id))"> <xsl:message terminate="yes"> <xsl:text>No id generated for </xsl:text> <xsl:copy-of select="."/> <xsl:text>: element not included in "for-elements" parameter.</xsl:text> </xsl:message> </xsl:if> <xsl:sequence select="$id"/> </xsl:template> </xsl:stylesheet>