XSLT – Numéroter les vers, tous les 5 vers, en TEI

Cette année, j’ai envie de lancer un peu l’initiative XSLT4TEI, l’XSLT pour la TEI. Pourquoi ? Et bien parce qu’on me pose beaucoup de questions sur XSLT et qu’à force d’y répondre, je me dis que ce serait bien de mutualiser, de créer de la documentation, de se former les uns les autres, etc. Alors outre la liste de diffusion (voir l’annonce dédiée), je me suis dit que rédiger des billets de blog pouvait être utile. En espérant que cela aide le plus grand nombre 🙂 AnneGF

Cas du jour : Comment numéroter des vers en TEI ?

Il s’agit de numéroter les vers, tous les 5 vers. Il y a, comme souvent, plusieurs possibilités. On peut enrichir la source en ajoutant l’attribut @n (évidemment pas à la main, ne vous en faites pas), ou bien on peut ajouter cette information à l’affichage, lors de la transformation XSLT. Bon, si la sortie est en HTML, il y aurait même fort probablement une solution en CSS à dire vrai mais je me concentre sur les solutions XSLT. Pour les 2 solutions que je propose, niveau choix, ça dépend de la source, de l’usage. J’aime bien ne pas alourdir la TEI d’informations qui peuvent se calculer automatiquement, mais d’un autre côté, quelqu’un qui accèderait au fichier TEI seul (sans la version HTML) aurait des difficultés à repérer un vers par son numéro à moins de savoir utiliser XPath, du coup… Je n’ai pas de réponse stricte et donc j’explique les deux méthodes.

Pour les impatient.e.s : aller directement à la méthode « Enrichissement de la source » ou à la méthode « Transfo à la génération de la sortie HTML » . Et hop,  un bonus en CSS 100% pour la route.

Commençons par un petit rappel mathématique et la présentation de <xsl:number/>. Rappel utile : une opération mathématique qui nous sera utile est le modulo qui permet de renvoyer le reste de la division d’un nombre par un autre. Pour faire simple, 10 modulo 5 égal 0 car 10 est multiple de 5 (10/5 = 2, sans reste) tandis que 11 modulo 5 égal 1 (si je divise 11 par 5, ça me donne 2 et il reste 1). Ainsi pour numéroter tous les 5 vers, je vais tester si le numéro du vers est multiple de 5, c’est-à-dire si le résultat de l’opération modulo 5 est bien égale à 0.

L’élément <xsl:number/> : cet élément permet de numéroter des éléments XML. Il dispose de quelques attributs fort utiles :

  • @level : indique comment la numérotation doit se faire. Doit-on retourner à zéro pour chaque sous élément (par exemple numéroter les vers au sein de leur <lg/>ou <div/> et repartir à 1 pour chaque nouvelle section) ? Doit-on numéroter tous les vers sur l’ensemble du fichier ? Ou bien doit-on produire une numérotation hiérarchique (comme pour des parties et sous-parties d’un livre par exemple). Les valeurs possibles sont respectivement single (par défaut), any et multiple. Une explication très claire est disponible ici : https://runebook.dev/fr/docs/xslt_xpath/xslt/element/number
  • @format, @count et d’autres attributs peuvent aussi être utiles. Tout est détaillé sur la W3School : https://www.w3schools.com/XML/ref_xsl_el_number.asp

Solution 1 : Enrichissement de la source

L’idée est de numéroter systématiquement tous les vers ; c’est ensuite, à l’affichage, que l’on choisira de n’afficher le numéro que si c’est un multiple de 5. On peut utiliser un XSLT de base “copie sauf” (trouvable ici) : celui-ci copie un XML-TEI à l’identique et il suffit d’y ajouter une règle pour traiter les <tei:l/> différemment. La règle a ajouter est la suivante :

<xsl:template match="tei:l">
        <xsl:element name="l" namespace="http://www.tei-c.org/ns/1.0">
            <xsl:copy-of select="@*"/>
            <xsl:attribute name="n">
                <xsl:number level="any"/>
            </xsl:attribute>
            <xsl:apply-templates/>
        </xsl:element>
  </xsl:template>

Solution 2 : Transformation au moment de générer la sortie (HTML dans notre exemple)

Et bien, c’est extrêmement ressemblant à la solution 1 mais la règle produira un contenu HTML plutôt qu’un attribut XML-TEI. De plus, ici on n’affiche le numéro que tous les 5 vers. Voici un exemple possible qui affiche le numéro entre crochets :

<xsl:template match="tei:l">
    <xsl:variable name="num_l">
      <xsl:number count="tei:l" level="any"/>
    </xsl:variable>
    <p>
      <xsl:if test="($num_l mod 5) = 0">
        <xsl:text>[</xsl:text>
        <xsl:value-of select="$num_l"/>
        <xsl:text>]</xsl:text>
      </xsl:if>
      <xsl:apply-templates/>
    </p>
  </xsl:template>

Et voici un autre exemple où l’on met le numéro dans un <span/> avec une classe HTML spécifique pour pouvoir gérer aisément l’affichage avec CSS :

<xsl:template match="tei:l">
        <xsl:variable name="num_l">
            <xsl:number count="tei:l" level="any"/>
        </xsl:variable>
        <p>
            <xsl:if test="($num_l mod 5) = 0">
                <span class="l_num">
                    <xsl:value-of select="$num_l"/>
                </span>
            </xsl:if>
            <xsl:apply-templates/>
        </p>
  </xsl:template>
Et pour finir, un peu de CSS (c’est cadeau !) :

Si on a généré <span class="numline">XXX</span>, on peut indiquer une mise en forme avec le sélecteur .numline. Par exemple :

.numline {
  display: none;
  vertical-align: top;
  color: grey;
  font-size: small;
  position: absolute;
  left: 1ex;
}

Ça, c’est la règle CSS appliquée sur le site du projet ENCHRE (cocher “Numéros de ligne” pour voir les numéros apparaître) : https://enchre.elan-numerique.fr/display/cahier-04/5

Et pour une solution 3 : 100% CSS

Voir par exemple ici pour des infos détaillées : https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Counter_Styles/Using_CSS_counters et toujours la W3School : https://www.w3schools.com/CSS/css_counters.asp

En supposant que les <tei:l/> soit transformés en <p class="line"/>, on peut utiliser :

p.line {
  counter-increment: listing;
}
p.line::before {
  content: counter(listing) ". ";
  display: inline-block;
  width: 8em;
  padding-left: -50px;
}

Si on ne veut numéroter que tous les 5 vers : on utilisera la pseudo classe :nth-of-type(5n). Ça donne un sélecteur comme : p.line:nth-of-type(5n)::before { /* règles CSS */ }, mais j’avoue que parfois je ne comprends pas tout à la façon qu’à CSS de numéroter les choses…

À la prochaine pour un peu plus de XSLT et rappelez-vous, si vous voulez échanger là-dessus, apprendre ou transmettre, n’hésitez pas à nous rejoindre sur la liste de diff !


OpenEdition vous propose de citer ce billet de la manière suivante :
Anne Garcia-Fernandez (1 septembre 2023). XSLT – Numéroter les vers, tous les 5 vers, en TEI. ELAN - L'élan littératures, arts et numériques de Litt&Arts (UMR 5316). Consulté le 16 mai 2025 à l’adresse https://doi.org/10.58079/o5fp


Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

This site uses Akismet to reduce spam. Learn how your comment data is processed.