<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl" xmlns:arr="http://www.edginet.org/arr" exclude-result-prefixes="arr" > <!-- Given a list of sermon files as an xml document this transformation creates an index file. --> <xsl:output method="xml" indent="yes" /> <xsl:template match="/"> <sermons> <xsl:for-each select="sermons/sermon"> <xsl:variable name="file">sermons/<xsl:value-of select="@file"/></xsl:variable> <xsl:apply-templates select="document($file)/sermon/info"/> </xsl:for-each> </sermons> </xsl:template> <xsl:template match="info"> <sermon> <xsl:copy-of select="name"/> <xsl:copy-of select="date"/> <xsl:copy-of select="title"/> <xsl:copy-of select="place"/> <!-- Store mainrefs for later use --> <xsl:variable name="refs-list"> <xsl:apply-templates select="mainref"/> <xsl:apply-templates select="extraref"/> <xsl:apply-templates select="/sermon/body//ref[@text]"/> </xsl:variable> <!-- Now refine the refs list before outputting it --> <xsl:choose> <xsl:when test="function-available('exsl:node-set')"> <xsl:apply-templates select="exsl:node-set($refs-list)/ref" mode="refine"> <!-- Sort refs so that supersets come before their subsets --> <xsl:sort select="./start" order="ascending" data-type="number"/> <xsl:sort select="./end" order="descending" data-type="number"/> </xsl:apply-templates> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="$refs-list/ref" mode="refine"> <!-- Sort refs so that supersets come before their subsets --> <xsl:sort select="./start" order="ascending" data-type="number"/> <xsl:sort select="./end" order="descending" data-type="number"/> </xsl:apply-templates> </xsl:otherwise> </xsl:choose> </sermon> </xsl:template> <xsl:template match="mainref|extraref"> <ref> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="name()='mainref'"><xsl:text>main</xsl:text></xsl:when> <xsl:otherwise><xsl:text>extra</xsl:text></xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:if test="name()='extraref'"> <xsl:attribute name="num"> <xsl:value-of select="position()"/> </xsl:attribute> </xsl:if> <text><xsl:copy-of select="node()"/></text> <xsl:variable name="start-end"> <xsl:call-template name="translate"> <xsl:with-param name="text" select="."/> </xsl:call-template> </xsl:variable> <start><xsl:value-of select="substring-before($start-end,':')"/></start> <end><xsl:value-of select="substring-after($start-end,':')"/></end> </ref> </xsl:template> <xsl:template match="ref[@text]"> <xsl:variable name="start-end"> <xsl:call-template name="translate"> <xsl:with-param name="text" select="@text"/> </xsl:call-template> </xsl:variable> <ref> <text><xsl:value-of select="@text"/></text> <start><xsl:value-of select="substring-before($start-end,':')"/></start> <end><xsl:value-of select="substring-after($start-end,':')"/></end> <!-- <name>REF<xsl:value-of select="generate-id(.)"/></name> --> <name>REF_<xsl:value-of select="count(preceding::ref)"/></name> </ref> </xsl:template> <!-- This template cleans up the refs list a bit --> <xsl:template match="ref" mode="refine"> <!-- eliminate subsets of the mainref from the list and subsets or duplicates of preceding refs. Use $start=current()/start $end=current()/end for clarity and efficiency. --> <xsl:variable name="start" select="start"/> <xsl:variable name="end" select="end"/> <xsl:if test="not(preceding-sibling::ref[$start>=start and end>=$end])"> <xsl:copy-of select="."/> </xsl:if> </xsl:template> <xsl:template name="translate"> <!-- The passage reference, eg. "2 Timothy 3:16-17" --> <xsl:param name="text"/> <!-- Strip the reference off the end. The first char may be numeric --> <xsl:variable name="booktmp"> <xsl:value-of select="substring($text,1,1)"/> <xsl:value-of select="translate(substring($text,2), '1234567890:-', '')"/> </xsl:variable> <!-- The canonical name of the book --> <xsl:variable name="booknam" select="normalize-space($booktmp)"/> <!-- The reference within the book --> <xsl:variable name="bookref" select="substring-after($text,$booktmp)"/> <!-- The number of the book: using keys is fast. --> <xsl:variable name="booknum"> <!-- change context to this stylesheet --> <xsl:for-each select="document('')"> <xsl:value-of select="key('book',$booknam)/@n"/> </xsl:for-each> </xsl:variable> <xsl:variable name="s0"> <xsl:choose> <xsl:when test="contains($bookref,'-')"> <xsl:value-of select="substring-before($bookref,'-')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$bookref"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="e0"> <xsl:choose> <xsl:when test="contains($bookref,'-')"> <xsl:value-of select="substring-after($bookref,'-')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$bookref"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- Insert chapter number into end ref if necessary --> <xsl:variable name="s1"> <xsl:value-of select="$s0"/> </xsl:variable> <xsl:variable name="e1"> <xsl:choose> <xsl:when test="not(contains($e0,':')) and contains($s0,':')"> <xsl:value-of select="concat(substring-before($s0,':'),':',$e0)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$e0"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- Detect whole chapters Make whole chapters start C:0 and end C:999. --> <xsl:variable name="s2"> <xsl:choose> <xsl:when test="not(contains($s1,':'))"> <xsl:value-of select="concat($s1,':0')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$s1"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="e2"> <xsl:choose> <xsl:when test="not(contains($e1,':'))"> <xsl:value-of select="concat($e1,':999')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$e1"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- start and end refs should now be in canonical form, C:V. Now translate to numerical form. --> <xsl:variable name="start"> <xsl:call-template name="trans"> <xsl:with-param name="ref" select="$s2"/> <xsl:with-param name="booknum" select="$booknum"/> </xsl:call-template> </xsl:variable> <xsl:variable name="end"> <xsl:call-template name="trans"> <xsl:with-param name="ref" select="$e2"/> <xsl:with-param name="booknum" select="$booknum"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="concat($start,':',$end)"/> </xsl:template> <xsl:template name="trans"> <xsl:param name="ref"/> <xsl:param name="booknum"/> <xsl:variable name="cs" select="substring-before($ref,':')"/> <xsl:variable name="vs" select="substring-after($ref,':')"/> <xsl:value-of select="$booknum"/> <xsl:value-of select="substring(concat('00',$cs),string-length($cs))"/> <xsl:value-of select="substring(concat('00',$vs),string-length($vs))"/> </xsl:template> <arr:books> <arr:book n="01">Genesis</arr:book> <arr:book n="02">Exodus</arr:book> <arr:book n="03">Leviticus</arr:book> <arr:book n="04">Numbers</arr:book> <arr:book n="05">Deuteronomy</arr:book> <arr:book n="06">Joshua</arr:book> <arr:book n="07">Judges</arr:book> <arr:book n="08">Ruth</arr:book> <arr:book n="09">1 Samuel</arr:book> <arr:book n="10">2 Samuel</arr:book> <arr:book n="11">1 Kings</arr:book> <arr:book n="12">2 Kings</arr:book> <arr:book n="13">1 Chronicles</arr:book> <arr:book n="14">2 Chronicles</arr:book> <arr:book n="15">Ezra</arr:book> <arr:book n="16">Nehemiah</arr:book> <arr:book n="17">Esther</arr:book> <arr:book n="18">Job</arr:book> <arr:book n="19">Psalm</arr:book> <arr:book n="20">Proverbs</arr:book> <arr:book n="21">Ecclesiastes</arr:book> <arr:book n="22">Song of Solomon</arr:book> <arr:book n="23">Isaiah</arr:book> <arr:book n="24">Jeremiah</arr:book> <arr:book n="25">Lamentations</arr:book> <arr:book n="26">Ezekiel</arr:book> <arr:book n="27">Daniel</arr:book> <arr:book n="28">Hosea</arr:book> <arr:book n="29">Joel</arr:book> <arr:book n="30">Amos</arr:book> <arr:book n="31">Obadiah</arr:book> <arr:book n="32">Jonah</arr:book> <arr:book n="33">Micah</arr:book> <arr:book n="34">Nahum</arr:book> <arr:book n="35">Habakkuk</arr:book> <arr:book n="36">Zephaniah</arr:book> <arr:book n="37">Haggai</arr:book> <arr:book n="38">Zechariah</arr:book> <arr:book n="39">Malachi</arr:book> <arr:book n="40">Matthew</arr:book> <arr:book n="41">Mark</arr:book> <arr:book n="42">Luke</arr:book> <arr:book n="43">John</arr:book> <arr:book n="44">Acts</arr:book> <arr:book n="45">Romans</arr:book> <arr:book n="46">1 Corinthians</arr:book> <arr:book n="47">2 Corinthians</arr:book> <arr:book n="48">Galatians</arr:book> <arr:book n="49">Ephesians</arr:book> <arr:book n="50">Philippians</arr:book> <arr:book n="51">Colossians</arr:book> <arr:book n="52">1 Thessalonians</arr:book> <arr:book n="53">2 Thessalonians</arr:book> <arr:book n="54">1 Timothy</arr:book> <arr:book n="55">2 Timothy</arr:book> <arr:book n="56">Titus</arr:book> <arr:book n="57">Philemon</arr:book> <arr:book n="58">Hebrews</arr:book> <arr:book n="59">James</arr:book> <arr:book n="60">1 Peter</arr:book> <arr:book n="61">2 Peter</arr:book> <arr:book n="62">1 John</arr:book> <arr:book n="63">2 John</arr:book> <arr:book n="64">3 John</arr:book> <arr:book n="65">Jude</arr:book> <arr:book n="66">Revelation</arr:book> </arr:books> <!-- Using keys is an efficient way to access the book data --> <xsl:key name="book" match="arr:book" use="."/> </xsl:stylesheet>