moteur XSLT - priorités

Nous avons vu que les patrons définis dans une feuille de style prévalent sur les patrons par défaut. Il peut aussi arriver que plusieurs patrons définis correspondent à un même élément. Qu'en est-il dans ce cas ?
Le processeur XSLT met en oeuvre un algorithme de calcul de priorités entre patrons et quelque soit le résultat, un seul patron est choisi (il n'y a jamais, pour un même élément, application de plusieurs patrons). Cet algorithme semble être propre à chaque processeur. On lit souvent que lorsque plusieurs patrons sont susceptibles d'être choisis, c'est le patron le plus spécifique qui est élu. Reste à définir la notion de spécificité...

Exemples
En reprenant le document XML précédent :
<?xml version="1.0" encoding="iso-8859-1"?>
<couples>
    <couple><form>Il</form><lemma>il</lemma></couple>
    <couple><form>était</form><lemma>être</lemma></couple>
    ...
    <couple><form>forêt</form><lemma>forêt</lemma></couple>
    <couple><form>.</form><lemma>.</lemma></couple>
</couples>

Étudions le résultat des transformations avec différentes feuilles de style :
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text"/>

    <!-- name(X) renvoie le nom de l'élément X -->
    <xsl:template match="text()">
        Patron générique : <xsl:value-of select="name(..)"/> - <xsl:value-of select="."/>
    </xsl:template>

    <xsl:template match="form/text()">
        Patron "form" : <xsl:value-of select="name(..)"/> - <xsl:value-of select="."/>
    </xsl:template>

</xsl:stylesheet>
  
Patron "form" : form - Il
Patron générique : lemma - il
Patron "form" : form - était
Patron générique : lemma - être
Patron "form" : form - forêt
Patron générique : lemma - forêt  
Patron "form" : form - .
Patron générique : lemma - .
Nous définissons ici deux patrons : le premier s'applique à tous les éléments de type text, quels qu'ils soient. Le second s'applique aux éléments de type text, fils des éléments form. Ici, "plus spécifique" prend le sens de "plus discriminant".
   
Il est cependant des cas où il est hasardeux de jouer sur la "spécificité implicite" :
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text"/>

    <xsl:template match="*">
        Patron générique : <xsl:value-of select="name(.)"/>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="form">
        Patron "form" : <xsl:value-of select="name(..)"/>
    </xsl:template>

</xsl:stylesheet>
  
Patron générique : couples  
Nous définissons ici un patron qui peut s'appliquer à tous les éléments et un patron s'appliquant aux éléments form (plus spécifique). Le résultat peut sembler surprenant, mais s'explique par l'ordre de parcours de l'arbre : le processeur considère tout d'abord l'élément racine et recherche les patrons qui peuvent être appliqués à cet élément. C'est le cas du premier patron. Il est donc appliqué, la racine a été traitée donc la transformation est terminée sans que le processeur ne descende plus bas dans l'arborescence.
   
En ajoutant l'instruction apply-templates dans le premier patron, le processeur considère récursivement les enfants des éléments correspondant à * et parcourt ainsi l'arbre en profondeur. Lorsqu'il est confronté aux éléments form, nous retrouvons la notion de spécificité entre * et form.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text"/>

    <xsl:template match="*">
        Patron générique : <xsl:value-of select="name(.)"/>
    </xsl:template>

    <xsl:template match="form">
        Patron "form" : <xsl:value-of select="name(..)"/>
    </xsl:template>

</xsl:stylesheet>
  
Patron générique : couples-
Patron générique : couple-
Patron "form" : couple
Patron générique : lemma-il
Patron générique : couple-
Patron "form" : couple
Patron générique : lemma-être
Patron générique : couple-
Patron "form" : couple
Patron générique : lemma-forêt
Patron générique : couple-
Patron "form" : couple
Patron générique : lemma-.
   
Autre cas difficilement décidable a priori :
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text"/>

    <!-- éléments de profondeur 3 -->
    <xsl:template match="/*/*/*">
        Patron "profondeur" : <xsl:value-of select="name(.)"/>
    </xsl:template>

    <!-- éléments form, où qu'ils se trouvent -->
    <xsl:template match="form">
        Patron "form" : <xsl:value-of select="."/>
    </xsl:template>

</xsl:stylesheet>
  
Patron "profondeur" : form - Il
Patron "profondeur" : lemma - il

Patron "profondeur" : form - était
Patron "profondeur" : lemma - être

Patron "profondeur" : form - forêt
Patron "profondeur" : lemma - forêt

Patron "profondeur" : form - .
Patron "profondeur" : lemma - .
Nous définissons ici un patron s'appliquant aux éléments de profondeur 3, quels qu'ils soient, et un patron spécifique aux éléments form (qui, dans le document XML, sont de profondeur 3). Dans le cas présent le premier patron est appliqué aux éléments form et lemma, mais il n'est pas dit qu'avec un autre processeur XSLT, le résultat soit identique.
   
Un moyen de rendre les priorités explicites lorsque plusieurs patrons sont applicables à un même type d'élément consiste à spécifier l'attribut priority des éléments templates.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text"/>

    <xsl:template match="/*/*/*" priority="1">
        Patron "profondeur" : <xsl:value-of select="name(.)"/>
    </xsl:template>

    <xsl:template match="form" priority="2">
        Patron "form" : <xsl:value-of select="."/>
    </xsl:template>

</xsl:stylesheet>
  
Patron "form" : Il
Patron "profondeur" : lemma - il

Patron "form" : était
Patron "profondeur" : lemma - être

Patron "form" : forêt
Patron "profondeur" : lemma - forêt

Patron "form" : .
Patron "profondeur" : lemma - .

Précédent... ] Sommaire... ] Suivant... ]