Déboguer · Publié le

Les 5 causes silencieuses d'un XSLT qui ne produit rien

La transformation se termine sans erreur et le fichier de sortie est vide. Cinq causes expliquent la quasi-totalité des cas, et aucune ne provoque de message.

Saxon rend 0, aucun message n'apparaît, et le fichier de sortie est vide — ou ne contient que la déclaration XML. Cinq causes expliquent la quasi-totalité de ces cas :

  1. le document source déclare un espace de noms que la feuille ignore ;
  2. le match désigne un élément qui n'existe pas sous ce nom ;
  3. xsl:apply-templates est appelé sans select, et la descente s'arrête ;
  4. le modèle par défaut s'applique et recopie le texte sans les balises ;
  5. la sortie part ailleurs, écrite par xsl:result-document.

Aucune ne produit d'erreur. C'est précisément ce qui les rend longues à trouver : un XSLT qui échoue vous le dit, un XSLT qui ne s'applique à rien se termine normalement.

Les cinq se distinguent en regardant ce qui sort, avant de relire la feuille.

Ce que vous observezCause probable
fichier vide, ou déclaration XML seuleespace de noms, ou match sans correspondance
du texte nu, sans une seule balisemodèle par défaut
une partie de l'arbre seulementapply-templates sans select
le fichier attendu reste vide, un autre est crééxsl:result-document

1. L'espace de noms que la feuille ignore

C'est la première par fréquence, et de loin. Le document source déclare un espace de noms par défaut :

XML
<facture xmlns="http://exemple.org/facturation">
  <lignes>
    <ligne reference="A-100">Clavier</ligne>
  </lignes>
</facture>

Et la feuille l'écrit sans préfixe :

XSLT
<xsl:template match="facture">
  <xsl:apply-templates select="lignes/ligne"/>
</xsl:template>

facture sans préfixe désigne l'élément facture sans espace de noms. Ce n'est pas le même nœud. Le modèle ne s'applique jamais, et rien ne le signale.

La correction déclare l'espace de noms et l'utilise :

XSLT
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:f="http://exemple.org/facturation">

  <xsl:template match="f:facture">
    <xsl:apply-templates select="f:lignes/f:ligne"/>
  </xsl:template>

</xsl:stylesheet>

⚠️ Le piège tient à une asymétrie du langage. Un élément sans préfixe dans un chemin XPath n'hérite pas de xmlns par défaut de la feuille — les attributs, eux, n'ont jamais d'espace de noms implicite. Deux règles différentes, la même syntaxe.

En XSLT 2.0 et au-delà, xpath-default-namespace sur xsl:stylesheet évite les préfixes partout. C'est confortable, mais cela rend le problème invisible le jour où le source change d'espace de noms : le chemin continue de se lire, il ne trouve simplement plus rien.

2. Un match qui ne désigne rien

Une faute de casse suffit. XML est sensible à la casse, <Ligne> et <ligne> sont deux éléments distincts, et un modèle qui vise le mauvais ne s'applique pas.

Le symptôme est identique à celui du cas précédent — sortie vide, aucun message —, ce qui explique qu'on cherche souvent l'espace de noms alors que le nom est simplement mal orthographié.

La façon la plus rapide de trancher entre 1 et 2 est de demander au processeur ce qu'il voit, plutôt que de relire :

XSLT
<xsl:template match="/">
  <xsl:message>racine : <xsl:value-of select="name(*)"/></xsl:message>
  <xsl:message>espace : <xsl:value-of select="namespace-uri(*)"/></xsl:message>
</xsl:template>

Un namespace-uri non vide alors que votre feuille n'en déclare aucun : c'est le cas 1. Un nom qui ne correspond pas à ce que vous attendiez : c'est le cas 2.

3. apply-templates sans select

Sans select, xsl:apply-templates traite les enfants du nœud courant, et rien de plus. Si la donnée utile se trouve deux niveaux plus bas et qu'aucun modèle ne prend le relais, la descente s'arrête au premier palier.

Le symptôme diffère des deux précédents : la sortie n'est pas vide, elle est partielle. C'est la distinction la plus utile de cet article — un fichier vide et un fichier incomplet n'ont pas les mêmes causes.

4. Le modèle par défaut

XSLT applique des règles implicites quand aucun modèle ne correspond. Celle qui compte ici : pour un nœud texte, le contenu est recopié tel quel.

C'est la cause du symptôme le plus déroutant — du texte sans une seule balise, comme si la feuille avait été ignorée. Elle ne l'a pas été : ses modèles ne se sont pas appliqués, et les règles par défaut ont pris la suite.

Pour l'écarter, désactivez la recopie et rendez le silence visible :

XSLT
<xsl:template match="text()"/>

Si la sortie devient vide, vous lisiez bien du texte recopié par défaut, et le vrai problème est l'un des trois précédents.

5. La sortie écrite ailleurs

xsl:result-document écrit dans un fichier distinct. Si la feuille l'emploie et que vous regardez la sortie principale, vous regardez un fichier que rien n'a rempli.

Il est fréquent que ce result-document soit dans une branche jamais atteinte : la sortie principale est vide et aucun fichier secondaire n'apparaît. On conclut alors à tort que rien ne s'est exécuté. C'est un cas assez particulier pour mériter son propre traitement — voir ce que Saxon exige des feuilles à sorties multiples.

Les limites de cette liste

Ces cinq causes couvrent la grande majorité des sorties vides, pas leur totalité. Restent au moins : une exception avalée par le programme appelant, une redirection de la sortie standard, un xsl:strip-space trop large, et les feuilles pilotées par des paramètres non transmis — pour celles-là, une variable vide a ses propres causes.

⚠️ Et un cas qu'aucune relecture ne rattrape : une transformation correcte dont la sortie est vide parce que la source l'est. Vérifiez la taille du fichier d'entrée avant de suspecter la feuille.

Voir ce qui s'applique, plutôt que le déduire

Les cinq cas ont un point commun : le premier réflexe utile n'est pas de relire la feuille, c'est de savoir quel modèle s'applique réellement. Les xsl:message ci-dessus le montrent, au prix d'une modification de la feuille et d'une deuxième exécution.

Un débogueur pas à pas répond à la même question sans y toucher : on suspend l'exécution à la racine, et on lit le nœud courant. C'est ce que décrit le chapitre déboguer du manuel, et poser un point d'arrêt dans une feuille de style montre la manipulation complète.

Sur le même sujet

Recevoir les nouveaux articles

Un message quand un article paraît. Rien d'autre : ni promotion, ni relance, ni lettre d'information.

Votre adresse ne sert qu'à cela et n'est transmise à personne. Un lien de désinscription accompagne chaque message. Confidentialité

Tous les articles