<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>