<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xdoc="http://www.pnp-software.com/XSLTdoc" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mods="http://www.loc.gov/mods/v3" xmlns:cs="http://purl.org/NET/xbiblio/csl" xmlns:db="http://docbook.org/ns/docbook" xmlns:bib="http://purl.org/NET/xbiblio/citeproc" version="2.0" exclude-result-prefixes="xdoc mods xs cs bib">
  
<!-- === licensed under CC-GNU GPL; see http://creativecommons.org/licenses/GPL/2.0 === -->
  
  <xdoc:doc type="stylesheet">
    
<xdoc:short>CiteProc functions.</xdoc:short>
    
<xdoc:author>Bruce D’Arcus</xdoc:author>
    
<xdoc:copyright>2004</xdoc:copyright>
  
</xdoc:doc>

  
<!-- |||| date functions |||| -->
  
  <xdoc:doc>when given a bibliographic record, returns its publication year</xdoc:doc>

  
<xsl:function name="mods:year">
    
<xsl:param name="bibref" as="element(mods:mods)" />
    
<xsl:for-each select="$bibref">
      
<xsl:variable name="xsd-date" select="(mods:originInfo/mods:dateIssued, mods:relatedItem/mods:originInfo/mods:dateIssued, mods:relatedItem/mods:part/mods:date)[1]" />
      
<xsl:value-of select="substring($xsd-date,1,4)" />
    
</xsl:for-each>
  
</xsl:function>
  
<!-- |||| number handling functions |||| -->
  
  <xdoc:doc>Collapses a page range according to the Chicago algorithm. Probably needs to be
    generalized.
</xdoc:doc>

  
<xsl:function name="bib:number-condense">
    
<xsl:param name="begin" />
    
<xsl:param name="end" />
    
<xsl:choose>
      
<xsl:when test="$begin castable as xs:integer">
        
<xsl:variable name="begin" select="xs:integer($begin)" as="xs:integer" />
        
<xsl:choose>
          
<xsl:when test="$begin gt 100 and $begin mod 100 and $begin idiv 100 eq $end idiv 100">
            
<xsl:value-of select="$end mod 100" />
          
</xsl:when>
          
<xsl:otherwise>
            
<xsl:value-of select="$end" />
          
</xsl:otherwise>
        
</xsl:choose>
      
</xsl:when>
      
<xsl:otherwise>
        
<xsl:value-of select="$end" />
      
</xsl:otherwise>
    
</xsl:choose>
  
</xsl:function>
  
<xsl:variable name="primary-contributors" select="('author', 'editor', 'creator', 'speaker', 'reviewer')" />
  
<xsl:variable name="secondary-contributors" select="('translator')" />
  
  <xdoc:doc>Constructs an authors string for grouping and sorting. This function concatenates all
    authors into a string so that multiple-authors get correctly grouped. Where no author exists it
    substitutes based on CSL definitions.
</xdoc:doc>

  
<xsl:function name="mods:grouping-key" as="xs:string">
    
<xsl:param name="bibref" as="element(mods:mods)" />
    
<xsl:variable name="sort-on" select="mods:sort_on($bibref)" as="xs:string" />
    
<xsl:choose>
      
<xsl:when test="$sort-on='creator'">
        
<xsl:value-of separator=";">
          
<xsl:for-each select="$bibref/mods:name[mods:role/mods:roleTerm=$primary-contributors]">
            
<xsl:value-of select="string-join((mods:namePart[@type='family'] | mods:namePart[not(@type)],mods:namePart[@type='given']), ',')" />
          
</xsl:for-each>
        
</xsl:value-of>
      
</xsl:when>
      
<xsl:when test="$sort-on='container-title'">
        
<xsl:value-of select="$bibref/mods:relatedItem[@type='host']/mods:titleInfo/mods:title" />
      
</xsl:when>
      
<xsl:when test="$sort-on='title'">
        
<xsl:value-of select="$bibref/mods:titleInfo/mods:title" />
      
</xsl:when>
      
<xsl:when test="$sort-on='anonymous'">
        
<xsl:value-of select="'Anonymous'" />
      
</xsl:when>
    
</xsl:choose>
  
</xsl:function>
  
  <xdoc:doc>Determines what to sort on.</xdoc:doc>

  
<xsl:function name="mods:sort_on" as="xs:string">
    
<xsl:param name="bibref" as="element(mods:mods)" />
    
<xsl:variable name="use-reftype" select="mods:use_csl-reftype($bibref)" />
    
<xsl:variable name="csl_path" select="if ($citeclass='note-nobib') then $style-citation/cs:first/cs:layout/cs:reftype[@name=$use-reftype] else $style-biblio/cs:layout/cs:reftype[@name=$use-reftype]" />
    
<xsl:choose>
      
<xsl:when test="$csl_path/cs:creator[1]">
        
<xsl:choose>
          
<xsl:when test="$bibref/mods:name[mods:role/mods:roleTerm=$primary-contributors]">
            
<xsl:value-of select="'creator'" />
          
</xsl:when>
          
<xsl:otherwise>
            
<xsl:choose>
              
<xsl:when test="$csl_path/cs:creator/@alternate-sortkey='container-title'">
                
<xsl:value-of select="'container-title'" />
              
</xsl:when>
              
<xsl:otherwise>
                
<xsl:value-of select="'anonymous'" />
              
</xsl:otherwise>
            
</xsl:choose>
          
</xsl:otherwise>
        
</xsl:choose>
      
</xsl:when>
      
<xsl:when test="$csl_path/cs:title[1]">
        
<xsl:value-of select="'title'" />
      
</xsl:when>
    
</xsl:choose>
  
</xsl:function>
  
  <xdoc:doc>Determines which CSL definition to use for any given MODS record.</xdoc:doc>

  
<xsl:function name="mods:use_csl-reftype" as="xs:string">
    
<xsl:param name="bibref" as="element(mods:mods)" />
    
<xsl:sequence select="if (mods:csl-reftype($bibref)) then (mods:csl-reftype($bibref)) else (mods:csl-fallback($bibref))" />
  
</xsl:function>
  
  <xdoc:doc>Maps a MODS reference type to a CSL XPATH expression.</xdoc:doc>

  
<xsl:function name="mods:csl-reftype" as="xs:string">
    
<xsl:param name="bibref" as="element(mods:mods)" />
    
<xsl:variable name="reftype" select="mods:reftype($bibref)" />
    
<xsl:variable name="csl-style" select="if ($citeclass='note-nobib') then ($style-citation/cs:first/cs:layout/cs:reftype) else ($style-biblio/cs:layout/cs:reftype)" />
    
<xsl:value-of select="$csl-style/@name[.=$reftype]" />
  
</xsl:function>
  
  <xdoc:doc>Determines the CSL fallback for a MODS record.</xdoc:doc>

  
<xsl:function name="mods:csl-fallback" as="xs:string">
    
<xsl:param name="bibref" as="element(mods:mods)" />
    
<xsl:variable name="bibrefclass" select="mods:refclass($bibref)" />
    
<xsl:choose>
      
<xsl:when test="$bibrefclass='monograph'">
        
<xsl:value-of select="'book'" />
      
</xsl:when>
      
<xsl:when test="$bibrefclass='part-inMonograph'">
        
<xsl:value-of select="'chapter'" />
      
</xsl:when>
      
<xsl:otherwise>
        
<xsl:value-of select="'article'" />
      
</xsl:otherwise>
    
</xsl:choose>
  
</xsl:function>
  
  <xdoc:doc>This function is central to the formatting logic of the system. The fallback system
    classifies records into one of three structural classes: part-inMongraph, part-inSerial, and
    mongraph. It would be easy to add serial as a fourth, but I have not yet found the need (does
    one ever cite a serial as a whole?).
</xdoc:doc>

  
<xsl:function name="mods:refclass" as="xs:string">
    
<xsl:param name="bibref" as="element(mods:mods)?" />
    
<xsl:choose>
      
<xsl:when test="$bibref/mods:relatedItem[@type='host']">
        
<xsl:variable name="issuance" select="$bibref/mods:relatedItem/mods:originInfo/mods:issuance" />
        
<xsl:choose>
          
<xsl:when test="$issuance='monographic'">part-inMonograph</xsl:when>
          
<xsl:otherwise>part-inSerial</xsl:otherwise>
        
</xsl:choose>
      
</xsl:when>
      
<xsl:otherwise>monograph</xsl:otherwise>
    
</xsl:choose>
  
</xsl:function>
  
  <xdoc:doc>Further classifies records into types based on the class. These types then map onto the
    citation style langauge definitions. Article, chapter and book are the default structures and
    generic fallbacks. Most records will be formatted with these "types." Beyond these core types,
    additional types would be defined by both their genre values and their likeness to the core
    types. The value can be multi-level where applicable: e.g. “article-magazine.”
</xdoc:doc>

  
<xsl:function name="mods:reftype" as="xs:string">
    
<xsl:param name="bibref" as="element(mods:mods)?" />
    
<xsl:value-of>
      
<xsl:choose>
        
<xsl:when test="$bibref/mods:relatedItem/@type = 'host'">
          
<xsl:variable name="issuance" select="$bibref/mods:relatedItem/mods:originInfo/mods:issuance" />
          
<xsl:choose>
            
<xsl:when test="mods:refclass($bibref) = 'part-inSerial'">
              
<xsl:if test="$bibref/mods:relatedItem/mods:genre=('periodical', 'magazine', 'academic journal', 'newspaper')">
                
<xsl:text>article</xsl:text>
                
<xsl:text>-</xsl:text>
              
</xsl:if>
              
<xsl:value-of select="($bibref/mods:relatedItem/mods:genre, $bibref/mods:genre)[1]" />
            
</xsl:when>
            
<xsl:when test="mods:refclass($bibref) = 'part-inMonograph'">
              
<xsl:choose>
                
<xsl:when test="$bibref/mods:genre">
                  
<xsl:value-of select="$bibref/mods:genre" />
                
</xsl:when>
                
<xsl:otherwise>
                  
<xsl:text>chapter</xsl:text>
                
</xsl:otherwise>
              
</xsl:choose>
            
</xsl:when>
            
<xsl:otherwise>
              
<xsl:value-of select="$bibref/mods:genre" />
            
</xsl:otherwise>
          
</xsl:choose>
        
</xsl:when>
        
<xsl:otherwise>book</xsl:otherwise>
      
</xsl:choose>
    
</xsl:value-of>
  
</xsl:function>
  
  <xdoc:doc>Numbers citations and foot/endnotes together.</xdoc:doc>

  
<xsl:function name="bib:number-footcite" as="xs:string">
    
<xsl:param name="footcite" as="element()" />
    
<xsl:choose>
      
<xsl:when test="$chapters/db:chapter">
        
<xsl:for-each select="$footcite">
          
<xsl:number level="any" select="." count="db:footnote|db:citation[not(ancestor::db:footnote)]" from="db:chapter" />
        
</xsl:for-each>
      
</xsl:when>
      
<xsl:otherwise>
        
<xsl:for-each select="$footcite">
          
<xsl:number level="any" select="." count="db:footnote|db:citation[not(ancestor::db:footnote)]" />
        
</xsl:for-each>
      
</xsl:otherwise>
    
</xsl:choose>
  
</xsl:function>
  
  <xdoc:doc>Determines the first time a reference is cited in the text. Necesary for those styles
    that make a formatting distinction between first and subsequent references.
</xdoc:doc>

  
<xsl:function name="bib:first-reference" as="xs:boolean">
    
<xsl:param name="cite-ref" as="node()" />
    
<xsl:sequence select="$cite-ref is key('refs', $cite-ref/@linkend, root($cite-ref))[1]" />
  
</xsl:function>
  
  <xdoc:doc>Determines when a citation fulfills the "ibid" condition.</xdoc:doc>

  
<xsl:function name="bib:ibid" as="xs:boolean">
    
<xsl:param name="citation" as="node()" />
    
<xsl:sequence select="$citation/db:biblioref/@linkend = $citation/preceding::db:biblioref[1]/@linkend" />
  
</xsl:function>
</xsl:stylesheet>






































v