<?xml version="1.0" encoding="UTF-8"?>
<!--
<h1>TEI » document (<a href="http://developpements.enc.sorbonne.fr/diple/transform/diple_split.xsl">diple_split.xsl</a>, <a href="http://developpements.enc.sorbonne.fr/diple/">Diple</a>)</h1>

© 2010, <a href="http://www.enc.sorbonne.fr/">École nationale des chartes</a>, <a href="http://www.cecill.info/licences/Licence_CeCILL-C_V1-fr.html">licence CeCILL-C</a> (LGPL compatible droit français)

<ul>
  <li>[VJ] <a onclick="this.href='mailto'+'\x3A'+'vincent.jolivet'+'\x40'+'enc.sorbonne.fr?subject=[diple_split.xsl] '">Vincent Jolivet</a></li>
  <li>[AG] <a onclick="this.href='mailto'+'\x3A'+'anna.gadre'+'\x40'+'enc.sorbonne.fr?subject=[diple_split.xsl] '">Anna Gadré</a></li>
  <li>[FG] <a onclick="this.href='mailto'+'\x3A'+'frederic.glorieux'+'\x40'+'enc.sorbonne.fr?subject=[diple_split.xsl] '">Frédéric Glorieux</a></li>
</ul>


Diple, factorisation d'outils utiles pour la division d'un fichier XML
en plusieurs fichiers HTML

Attention, cette transformation n'a d'intérêt qu'importée par un pilote
qui importera aussi une transformation vers HTML



-->
<xsl:transform version="1.1"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:tei="http://www.tei-c.org/ns/1.0"
  exclude-result-prefixes="tei"
>
  <!-- Ne pas importer diple_html.xsl ici, ou bien impossible que corpus_html.xsl prenne la main dans corpus_split.xsl -->
  <!-- xsl:import href="diple_html.xsl"/ --> 
  <!-- extension des fichiers générés, paramétrable de l'extérieur -->
  <xsl:param name="_html">.html</xsl:param>
  <!-- dossier de projection des fichiers générés, paramétrable de l'extérieur -->
  <xsl:param name="dir">html/</xsl:param>
  <!-- Dossier où retrouver des ressources de thème -->
  <xsl:param name="theme">theme/</xsl:param>
  <!-- Clé par défaut sur les éléments à spliter -->
  <xsl:key name="split" match="*[descendant-or-self::*[contains(@subtype, 'article')]] | *[descendant-or-self::*[contains(@subtype, 'split')]] | tei:text" use="generate-id(.)"/>
  <!-- paramètre permettant de tester d'où fonctionne un template -->
  <xsl:param name="this">tei_split</xsl:param>
  <!-- Racine -->
  <xsl:template match="/">
    <!-- Générer la navigation -->
    <xsl:variable name="href">
      <xsl:value-of select="$dir"/>
      <xsl:if test="$bookId != ''">
        <xsl:value-of select="$bookId"/>
        <xsl:text>_</xsl:text>
      </xsl:if>
      <xsl:text>nav</xsl:text>
      <xsl:value-of select="$_html"/>
    </xsl:variable>
    <xsl:message>
      <xsl:value-of select="$href"/>
    </xsl:message>
    <xsl:document 
      href="{$href}" 
      omit-xml-declaration="no" 
      encoding="UTF-8" 
      indent="yes" 
      doctype-public="html"
    >
      <html lang="fr" xml:lang="fr">
        <head>
          <title>
            <xsl:call-template name="title"/>
            <xsl:text>, navigation</xsl:text>
          </title>
          <!-- lien à une CSS pour les fichiers statiques -->
          <link rel="stylesheet" type="text/css" href="{$theme}html.css"/>
          <link rel="stylesheet" type="text/css" href="{$theme}diple_html.css"/>
          <link rel="stylesheet" type="text/css" href="{$theme}{$corpusId}.css"/>
          <script type="text/javascript" src="{$theme}Tree.js">//</script>
        </head>
        <body class="nav {$corpusId}">
          <xsl:call-template name="nav"/>
        </body>
      </html>
    </xsl:document>
    <!-- Traverser le document pour voir les documents à créer -->
    <xsl:apply-templates mode="split"/>
    <date>
      <xsl:value-of select="$date"/>
    </date>
    <!-- le corpus en une seule page ne peut pas être généré ici car le contexte de résolution des liens est différent -->
  </xsl:template>
  <!-- Réécriture des liens -->
  <xsl:template match="*" mode="href" name="href">
    <xsl:choose>
      <!-- Racine -->
      <xsl:when test="(count(/|.) = 1) or (count(/*|.) = 1)">.</xsl:when>
      <!-- Structure TEI, renommés par le template "id" -->
      <xsl:when test="local-name(../..)='TEI'">
        <xsl:call-template name="id"/>
        <xsl:value-of select="$_html"/>
      </xsl:when>
      <!-- Contient ou est un élément à spliter, spliter -->
      <xsl:when test="descendant-or-self::*[key('split', generate-id())]">
        <xsl:call-template name="id"/>
        <xsl:value-of select="$_html"/>
      </xsl:when>
      <!-- Enfant d'une page, id du parent splité + ancre -->
      <xsl:when test="ancestor::*[key('split', generate-id())]">
        <xsl:for-each select="ancestor::*[key('split', generate-id())][1]">
          <xsl:call-template name="id"/>
          <xsl:value-of select="$_html"/>
        </xsl:for-each>
        <xsl:text>#</xsl:text>
        <xsl:call-template name="id"/>
      </xsl:when>
      <!-- A été rencontré, laissé pour mémoire -->
      <xsl:when test="ancestor::tei:*[local-name(../..)='TEI']">
        <xsl:for-each select="ancestor::tei:*[local-name(../..)='TEI'][1]">
          <xsl:call-template name="id"/>
          <xsl:value-of select="$_html"/>
        </xsl:for-each>
        <xsl:text>#</xsl:text>
        <xsl:call-template name="id"/>
      </xsl:when>
      <!-- Pas de split, juste des ancres -->
      <xsl:otherwise>
        <xsl:text>#</xsl:text>
        <xsl:call-template name="id"/>
      </xsl:otherwise>
    </xsl:choose>    
  </xsl:template>
  <!-- Par défaut, traverser -->
  <xsl:template match="*" mode="split">
    <xsl:apply-templates mode="split"/>
  </xsl:template>
  <!-- Arrêter le texte -->
  <xsl:template match="text()" mode="split"/>
  <!-- Licence -->
  <xsl:template match="tei:publicationStmt" mode="split">
    <xsl:call-template name="document">
      <xsl:with-param name="id">
        <xsl:if test="$bookId != ''">
          <xsl:value-of select="$bookId"/>
          <xsl:text>_</xsl:text>
        </xsl:if>
        <xsl:text>licence</xsl:text>
      </xsl:with-param>
    </xsl:call-template>
  </xsl:template>
  <!-- Intro, corps, conclu : split -->
  <xsl:template match="/*/tei:text/*" mode="split">
    <xsl:call-template name="document"/>
  </xsl:template>
  <!-- Prendre la main sur ci dessous pour bien passer à travers -->
  <xsl:template match="/* | /*/tei:text | tei:group/tei:text/tei:body " mode="split" priority="5">
    <xsl:apply-templates mode="split"/>
  </xsl:template>
  <!-- Crédits -->
  <xsl:template match="tei:titleStmt" mode="split">
    <xsl:call-template name="document">
      <xsl:with-param name="id">
        <xsl:if test="$bookId != ''">
          <xsl:value-of select="$bookId"/>
          <xsl:text>_</xsl:text>
        </xsl:if>
        <xsl:text>credits</xsl:text>
      </xsl:with-param>
    </xsl:call-template>
  </xsl:template>
  <!-- head html -->
  <xsl:template name="head">
    
  </xsl:template>
  <xsl:template match="
    tei:text | tei:body | tei:front | tei:back | tei:group |
    tei:div | tei:div0 | tei:div1 | tei:div2 | tei:div3 | tei:div4 | tei:div5 | tei:div6 | tei:div7 
    "
    mode="split">
    <xsl:choose>
      <!-- article, créer un document -->
      <xsl:when test="key('split', generate-id()) or descendant::*[key('split', generate-id())]">
        <xsl:call-template name="document"/>
      </xsl:when>
      <!-- sortir le html -->
      <xsl:otherwise>
        <xsl:apply-templates select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  <!-- Pour section à spliter -->
  <xsl:template name="document">
    <xsl:param name="id">
      <xsl:call-template name="id"/>
    </xsl:param>
    <xsl:param name="href">
      <xsl:value-of select="$dir"/>
      <xsl:value-of select="$id"/>
      <xsl:value-of select="$_html"/>
    </xsl:param>
    <xsl:param name="title">
      <xsl:call-template name="titleBranch"/>
    </xsl:param>
    <!-- Un contenu généré par ailleurs -->
    <xsl:param name="article"/>
    <xsl:message>
      <xsl:value-of select="$href"/>
      <xsl:text> : </xsl:text>
      <xsl:call-template name="idpath"/>
    </xsl:message>
    <xsl:document 
      href="{$href}" 
      omit-xml-declaration="no" 
      encoding="UTF-8" 
      indent="yes" 
      doctype-public="html"
    >
      <html xml:lang="fr"   
        xmlns:dc="http://purl.org/dc/terms/"
        xmlns:dbo="http://dbpedia.org/ontology/"
      >
        <head>
          <meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
          <title>
            <xsl:value-of select="normalize-space($title)"/>
          </title>
          <xsl:variable name="label">
            <xsl:if test="ancestor::tei:text[@n]">
              <xsl:value-of select="ancestor::tei:text/@n"/>
              <xsl:text>, </xsl:text>
            </xsl:if>
            <xsl:apply-templates select="." mode="label"/>
          </xsl:variable>
          <meta name="label" content="{normalize-space($label)}"/>
          <!-- lien à une CSS pour les fichiers statiques -->
          <link rel="stylesheet" type="text/css" href="{$theme}html.css"/>
          <link rel="stylesheet" type="text/css" href="{$theme}diple_html.css"/>
          <link rel="stylesheet" type="text/css" href="{$theme}{$corpusId}.css"/>
          <!-- Permet ici d'ajouter des metas -->
          <xsl:apply-templates select="." mode="meta"/>
          <!-- Nécessaire pour tous les items, notamment crédits ou licence, qui n'ont pas le titre de corpus dans leur héritage -->
          <link rel="dc:isPartOf" href="." title="{normalize-space($corpusTitle)}"/>
          <!-- utile au fil d'ariane, ne pas sortir le body, serait égal à ci-dessus -->
          <xsl:for-each select="ancestor::*[ancestor::tei:body or ancestor::tei:group][not(self::tei:body)]">
            <!-- URI (identifier) suppose flat file  -->
            <xsl:variable name="ancestorId">
              <xsl:call-template name="id"/>
            </xsl:variable>
            <xsl:variable name="ancestorHref">
              <xsl:choose>
                <!-- @id="bookId_articleId" translate to @href="articleId" -->
                <xsl:when test="contains($ancestorId, concat($bookId, '_'))">
                  <xsl:value-of select="substring-after($ancestorId, concat($bookId, '_'))"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="$ancestorId"/>
                </xsl:otherwise>
              </xsl:choose>              
            </xsl:variable>
            <xsl:variable name="ancestorLabel">
              <xsl:apply-templates select="." mode="label"/>
            </xsl:variable>
            <link rel="dc:isPartOf" href="{$ancestorHref}" title="{normalize-space($ancestorLabel)}"/>
          </xsl:for-each>
        </head>
        <body class="article {$corpusId}">
          <xsl:choose>
            <!-- Contenu passé en paramètre -->
            <xsl:when test="$article">
              <xsl:copy-of select="$article"/>
            </xsl:when>
            <!-- Page d'accueil, ajouter un peu de navigation -->
            <xsl:when test="$id = 'index'">
              <!-- Procéder les éléments qui ne splitent pas -->
              <article>
                <xsl:call-template name="atts"/>
                <xsl:apply-templates select="*[not(key('split', generate-id())) and not(descendant::*[key('split', generate-id())])]"/>
              </article>
              <!-- table des matières complète -->
              <xsl:if test="self::tei:front and tei:div">
                <!--
                <strong>
                  <xsl:call-template name="label">
                    <xsl:with-param name="id">front</xsl:with-param>
                  </xsl:call-template>
                </strong>
                -->
                <xsl:apply-templates select="." mode="ul"/>
                <hr/>
              </xsl:if>
              <xsl:apply-templates select="../tei:body | ../tei:group " mode="ul"/>
              <xsl:if test="../tei:back/tei:div">
                <hr/>
                <xsl:apply-templates select="../tei:back " mode="ul"/>
              </xsl:if>
            </xsl:when>
            <!-- avec des enfants à spliter -->
            <xsl:when test="descendant::*[key('split', generate-id())]">
              <xsl:call-template name="prevnext"/>
              <article>
                <xsl:call-template name="atts"/>
                <!-- sortir les enfants qui ne sont pas des feuilles de split -->
                <xsl:apply-templates select="*[not(key('split', generate-id()))]"/>
                <!-- les notes, passer les noeud sur lesquels générer -->
                <xsl:variable name="notes">
                  <xsl:call-template name="notes">
                    <xsl:with-param name="text" select="*[not(key('split', generate-id()))]"/>
                  </xsl:call-template>
                </xsl:variable>
                <xsl:if test="$notes != ''">
                  <footer>
                    <xsl:copy-of select="$notes"/>
                  </footer>
                </xsl:if>
                <!-- Sert aussi en cas de section vide -->
                <xsl:text> </xsl:text>
              </article>
              <ul>
                <xsl:choose>
                  <xsl:when test="tei:body">
                    <xsl:for-each select="tei:body/*[key('split', generate-id())]">
                      <li>
                        <xsl:apply-templates select="." mode="a"/>
                      </li>
                    </xsl:for-each>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:for-each select="*[ descendant-or-self::*[key('split', generate-id())]]">
                      <li>
                        <xsl:apply-templates select="." mode="a"/>
                      </li>
                    </xsl:for-each>
                  </xsl:otherwise>
                </xsl:choose>
              </ul>
            </xsl:when>
            <!-- Feuille de l'arbre à split -->
            <xsl:otherwise>
              <xsl:variable name="prevnext">
                <xsl:call-template name="prevnext"/>
              </xsl:variable>
              <xsl:copy-of select="$prevnext"/>
              <article>
                <xsl:call-template name="atts"/>
                <!-- 
Tester si saut de page en milieu de texte pour récupérer le précédent.
Attention, pas .//tei:pb[1] (= tous les pb ainés) ni ./following:: (= saut de page après la section)
si du texte avant le premier saut de page, prendre le précédent
                -->
                <xsl:if test=".//tei:pb and local-name(*[1])!='pb'">
                  <xsl:variable name="pb" select="node()[1]/following::tei:pb[1]"/>
                  <xsl:if test=".//text()[count($pb|following::tei:pb[1])=1][normalize-space(.) != '']">
                    <xsl:apply-templates select="preceding::tei:pb[1]"/>
                  </xsl:if>
                </xsl:if>
                <xsl:apply-templates/>
                <xsl:if test="$id = 'credits'">
                  <!-- Histoire des modifications (si pas public, mettre display none en CSS) -->
                  <xsl:apply-templates select="/*/tei:teiHeader/tei:revisionDesc"/>
                </xsl:if>
                <xsl:variable name="notes">
                  <xsl:call-template name="notes"/>
                </xsl:variable>
                <xsl:if test="$notes != ''">
                  <footer>
                    <xsl:copy-of select="$notes"/>
                  </footer>
                </xsl:if>
              </article>
              <xsl:copy-of select="$prevnext"/>
            </xsl:otherwise>
          </xsl:choose>
        </body>
      </html>
    </xsl:document>
    <!-- Autres sections susceptibles de produire des pages -->
    <xsl:apply-templates select="*[ descendant-or-self::*[key('split', generate-id())] ]" mode="split"/>
  </xsl:template>

  
  
  <!-- Mode meta pour item, par défaut RIEN -->
  <xsl:template match="node()" mode="meta"/>
  <!-- Un exemple de surcharge de ce mode pour ajouter des métas spécifiques à un corpus -->
  <xsl:template match="*[tei:num or tei:head/tei:num]" mode="meta">
    <meta name="num" content="{normalize-space(tei:num|tei:head/tei:num)}" />
  </xsl:template>
  <!-- h1 en sommet d'item, et calcul relatif de hiérarchie -->
  <xsl:template match="
      tei:div/tei:head
    | tei:div0/tei:head
    | tei:div1/tei:head
    | tei:div2/tei:head
    | tei:div3/tei:head
    | tei:div4/tei:head
    | tei:div5/tei:head
    | tei:div6/tei:head
    | tei:div7/tei:head
    | tei:front/tei:head 
    | tei:back/tei:head 
    | tei:body/tei:head 
    | tei:text/tei:head
  ">
    <!-- Nombre d'ascendants, s'arrêter à la première page splitée -->
    <xsl:variable name="niv" select="
      count(
        ancestor::tei:*[not(descendant::*[key('split', generate-id())]) and local-name()!='front']
      ) "/>
    <xsl:choose>
      <xsl:when test="number($niv) &lt; 2">
        <h1>
          <xsl:call-template name="atts"/>
          <xsl:apply-templates/>
        </h1>
      </xsl:when>
      <xsl:when test="$niv &gt; 7">
        <h6>
          <xsl:call-template name="atts"/>
          <xsl:apply-templates/>
        </h6>
      </xsl:when>
      <xsl:otherwise>
        <xsl:element name="h{$niv}">
          <xsl:call-template name="atts"/>
          <xsl:apply-templates/>
        </xsl:element>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- génération d'une navigation précédent/suivant -->
  <xsl:template name="prevnext">
    <xsl:text>

</xsl:text>
    <nav class="prevnext" style="text-align:center;">
    <xsl:text>
</xsl:text>
      <span class="prev" style="float:left">
        <!-- lien vers l'élément juste avant, même si c'est un petit cousin
        laisser le test @xml:id, sinon risque d'aller dans des pages qui n'ont pas été générées 
        for-each a l'air moins gourmand qu'un apply-templates
        PERF : preceding::*[ descendant-or-self::*[key('split', generate-id())]][1]
        -->
        <xsl:for-each select="preceding::*[key('split', generate-id())][1]">
          <xsl:call-template name="a-label"/>
        </xsl:for-each>
        <!-- Laisser l'espace insécable, si case vide -->
        <xsl:text> </xsl:text>
      </span>
    <xsl:text>
</xsl:text>
      <span class="next" style="float:right">
        <xsl:text> </xsl:text>
        <xsl:variable name="enfant">
          <xsl:for-each select="*[key('split', generate-id()) and local-name()!='body'][1]">
            <xsl:call-template name="a-label">
              <xsl:with-param name="rel">next</xsl:with-param>
            </xsl:call-template>
          </xsl:for-each>
        </xsl:variable>
        <xsl:choose>
          <xsl:when test="$enfant != ''">
            <xsl:copy-of select="$enfant"/>
          </xsl:when>
          <xsl:otherwise>
          <!-- premier descendant splité (attention à text/body/div[@split]) -->
            <xsl:variable name="descendant">
              <xsl:for-each select="descendant::*[key('split', generate-id()) and local-name()!='body'][1]">
                <xsl:call-template name="a-label">
                  <xsl:with-param name="rel">next</xsl:with-param>
                </xsl:call-template>
              </xsl:for-each>
            </xsl:variable>
            <xsl:choose>
              <xsl:when test="$descendant != ''">
                <xsl:copy-of select="$descendant"/>
              </xsl:when>
              <!-- suivant -->
              <xsl:otherwise>
                <xsl:for-each select="following::*[key('split', generate-id())][1]">
                  <xsl:call-template name="a-label">
                    <xsl:with-param name="rel">next</xsl:with-param>
                  </xsl:call-template>
                </xsl:for-each>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:otherwise>
        </xsl:choose>
      </span>
    <xsl:text>
</xsl:text>
      <!-- afficher les chapitres parents -->
      <xsl:if test="ancestor-or-self::tei:*[@xml:id|tei:head|@id][local-name()!='TEI']">
        <div class="up">
          <xsl:for-each select="ancestor-or-self::tei:*[@xml:id|tei:head|@id][local-name()!='TEI'] ">
            <div>
              <xsl:call-template name="a-label">
                <xsl:with-param name="rel">up</xsl:with-param>
              </xsl:call-template>
            </div>
          </xsl:for-each>
        </div>
      </xsl:if>
    <xsl:text>
</xsl:text>
    </nav>
    <xsl:text>
      
</xsl:text>
  </xsl:template>
  <!-- Plus efficace qu'une xpath lourde.
preceding::*[ descendant-or-self::*[key('split', generate-id())] ][1]
  -->
  <xsl:template match="*" mode="prev" name="prev-a">
    <xsl:param name="secure"/>
    <xsl:choose>
      <xsl:when test="not($secure)">
        <xsl:apply-templates select="preceding::*[1]" mode="prev">
          <xsl:with-param name="secure" select="true()"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:when test="descendant-or-self::*[key('split', generate-id())]">
        <xsl:call-template name="a-label"/>
      </xsl:when>
      <xsl:when test="not(preceding::*[1])"/>
      <xsl:otherwise>
        <xsl:apply-templates select="preceding::*[1]" mode="prev">
          <xsl:with-param name="secure" select="true()"/>
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  <!-- lien de section prevnext -->
  <xsl:template name="a-label">
    <xsl:param name="rel"/>
    <a>
      <xsl:attribute name="href">
        <xsl:call-template name="href"/>
      </xsl:attribute>
      <xsl:if test="$rel">
        <xsl:attribute name="rel">
          <xsl:value-of select="$rel"/>
        </xsl:attribute>
      </xsl:if>
      <xsl:variable name="t">
        <xsl:apply-templates select="." mode="title"/>
      </xsl:variable>
      <xsl:variable name="title" select="normalize-space($t)"/>      
      <xsl:choose>
        <xsl:when test="$title &lt; 50">
          <xsl:value-of select="$title"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:attribute name="title">
            <xsl:value-of select="$title"/>
          </xsl:attribute>
          <xsl:value-of select="substring($title, 1, 30)"/>
          <xsl:value-of select="substring-before(concat(substring($title, 31), ' '), ' ')"/>
          <!-- Quelque chose a été coupé -->
          <xsl:if test="substring-after(substring($title, 30), ' ') != ''">…</xsl:if>
        </xsl:otherwise>
      </xsl:choose>
    </a>
  </xsl:template>

</xsl:transform>
