Lire une trace d'erreur Saxon sans la deviner
Les messages de Saxon nomment le fichier et la ligne, mais rarement la cause. Trois familles de messages couvrent l'essentiel, et chacune se lit différemment.
Un message d'erreur Saxon commence par un code de quatre lettres suivi de quatre chiffres. Le préfixe dit quel fichier ouvrir — et c'est l'information la plus utile de la ligne, parce qu'elle évite de relire le mauvais.
| Préfixe | Origine | Le fichier à ouvrir |
|---|---|---|
SXXP | analyse du document source | le XML d'entrée, pas la feuille |
XPTY | type XPath incompatible | l'expression, et le type qu'elle reçoit |
XTDE | erreur dynamique de transformation | le modèle en cours d'exécution |
XTSE | erreur statique de la feuille | la feuille, avant toute exécution |
Trois de ces familles surviennent pendant l'exécution ; la quatrième, XTSE, avant même qu'elle
commence. ⚠️ La distinction compte : un XTSE signifie que rien n'a tourné, et chercher la
cause dans les données est une perte de temps.
SXXP — c'est la source, pas la feuille
SXXP0003 est le plus fréquent : « Error reported by XML parser ». Saxon n'a pas transformé quoi
que ce soit, il n'a pas réussi à lire le document d'entrée.
Les causes habituelles sont banales et n'ont rien à voir avec XSLT : une balise non fermée, une
esperluette nue au lieu de &, un octet illégal pour l'encodage déclaré, ou une DTD référencée
que le processeur ne trouve pas.
🔴 Le réflexe qui fait perdre le plus de temps est de relire la feuille de style. Ouvrez le XML d'entrée. S'il est volumineux, la ligne annoncée par le parseur est fiable — c'est un des rares cas où elle l'est complètement.
XPTY — le type reçu, pas le type attendu
XPTY0004 est le code de l'incompatibilité de type. Saxon l'accompagne presque toujours d'une
phrase de la forme :
Required item type of first argument of fn:sum() is xs:anyAtomicType;
supplied value has item type element(montant)
Lisez la seconde ligne avant la première. L'attendu, vous le connaissez ; c'est le fourni qui vous apprend quelque chose — ici, que l'expression rend des éléments là où une fonction numérique attend des valeurs atomiques.
Le cas typique vient d'un chemin qui remonte des nœuds quand on croyait obtenir des nombres :
<xsl:variable name="total" select="sum(ligne/montant)"/>
En XSLT 2.0 et au-delà, l'atomisation est implicite pour sum(), et ceci fonctionne — sauf si
montant porte un type de schéma incompatible, ou contient du texte non numérique. Le message
nomme alors le type réellement rencontré, et c'est la réponse.
⚠️ Un XPTY0004 sur une expression manifestement correcte signale presque toujours une donnée
inattendue, pas une feuille fautive. Un seul <montant>N/A</montant> dans dix mille lignes
suffit.
XTDE — pendant la transformation
Les XTDE surviennent en cours d'exécution, quand la feuille est valide mais qu'une situation la
met en défaut. XTDE1490 en est un bon exemple : deux écritures dans le même fichier de sortie via
xsl:result-document.
Ce qu'il faut retenir : le fichier à ouvrir est le modèle en cours, et la difficulté est de savoir lequel c'est. C'est précisément là que le numéro de ligne devient trompeur.
Pourquoi la ligne annoncée n'est pas toujours la bonne
Saxon évalue xsl:variable paresseusement : la valeur n'est calculée qu'au premier usage réel,
pas à la déclaration.
<xsl:variable name="total" select="sum(ligne/montant)"/>
<!-- ... cinquante lignes plus loin ... -->
<xsl:value-of select="$total + 1"/>
L'erreur est rapportée sur le xsl:value-of, parce que c'est là qu'elle s'est produite. La cause
est sur la déclaration. Le numéro de ligne n'est pas faux — il désigne l'endroit où le problème
s'est manifesté, pas celui où il a été écrit.
La même chose vaut pour une variable passée en paramètre : le message pointe le modèle appelé, la cause est chez l'appelant.
⚠️ La règle pratique : quand la ligne annoncée contient une variable, la lecture commence à la définition de cette variable, pas à la ligne annoncée.
Ce que cet article ne couvre pas
Les quatre familles ci-dessus laissent de côté au moins :
FORGetFOCA, les erreurs de fonctions et de conversion —FORG0001sur unxs:datemalformé, par exemple ;XPDY0002, l'absence d'élément de contexte, typique d'une expression évaluée hors de tout nœud courant ;XTMM9000, la terminaison volontaire par<xsl:message terminate="yes"/>— ce n'est pas une erreur du processeur mais une erreur écrite par vous, et le message est le vôtre ;- les erreurs remontées par une extension ou par le programme appelant, qui peuvent masquer le code d'origine.
🔴 Et un cas qu'aucune lecture de code ne rattrape : une trace tronquée. Beaucoup d'intégrations n'affichent que le premier message et jettent la cause chaînée. Si votre message se termine par une phrase générique sans code, ce n'est pas Saxon qui manque de précision — c'est ce qui l'enveloppe.
Savoir où l'on est, au lieu de le reconstituer
Les trois familles se lisent bien une fois qu'on sait quel modèle s'exécutait. Sur une feuille de quelques centaines de lignes, on le reconstitue de tête ; passé cette taille, on le devine.
Suspendre l'exécution à l'endroit signalé et remonter la pile répond à la question sans hypothèse : 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. Le cas voisin — une transformation qui ne produit rien du tout, sans le moindre message — a ses propres causes, décrites dans les cinq causes silencieuses d'un XSLT vide.