Sorties multiples : ce que Saxon exige vraiment
xsl:result-document échoue sur « no base output URI » alors que la feuille est correcte. L'exigence porte sur la façon dont la transformation est lancée, pas sur la feuille.
Error: no base output URI supplied
La feuille de style est correcte, et c'est ce qui rend le message déroutant : il ne désigne rien dans le fichier qu'on vient d'écrire.
xsl:result-document reçoit un href relatif. Relatif à quoi ? À l'URI de base de sortie,
que Saxon déduit normalement de la destination principale de la transformation. Quand on n'en a pas
donné — sortie vers un flux en mémoire, vers la console, vers un Writer fourni par l'appelant —
il n'y a aucun point d'ancrage, et Saxon refuse plutôt que d'écrire dans un répertoire courant qu'il
n'a pas choisi.
🔴 L'exigence porte donc sur l'appel, jamais sur la feuille. Tant qu'on cherche la faute dans le XSLT, on ne la trouve pas.
<xsl:result-document href="lignes/{@id}.xml" method="xml">
<xsl:apply-templates/>
</xsl:result-document>
Les trois façons de fournir l'ancrage
1. Donner une sortie principale, même si la transformation n'écrit rien dedans. C'est la voie la plus courte en ligne de commande :
java -jar saxon.jar -s:facture.xml -xsl:eclater.xsl -o:sortie/index.xml
Les fichiers partent alors dans sortie/lignes/. ⚠️ Le fichier principal est créé même vide — un
index.xml de zéro octet à côté des vrais résultats n'est pas un bogue, c'est l'ancre.
2. Fournir l'URI explicitement. Depuis l'API s9api, setBaseOutputURI sur le transformeur
règle la question sans imposer de sortie principale. C'est la bonne réponse quand le résultat
principal n'a aucun sens — un éclatement pur, où tout part en fichiers annexes.
3. N'employer que des URI absolues dans href. Cela marche partout et fige les chemins : la
feuille cesse d'être déplaçable, et un chemin absolu écrit sous Windows ne se rejoue pas ailleurs.
À réserver aux cas où la destination est réellement fixe.
Ce qui casse ensuite
⚠️ Deux xsl:result-document visant la même URI dans une même transformation sont une erreur
(XTDE1490), pas un écrasement silencieux. Le message ne nomme pas les deux instructions fautives,
et c'est ce qui rend le défaut long à situer : quand l'URI est calculée — {@id} — il faut d'abord
prouver que deux nœuds portent le même identifiant.
⚠️ Chaque document produit a ses propres attributs de sérialisation. Un xsl:output global ne
s'applique pas automatiquement aux résultats secondaires : encodage, indentation et méthode se
redéclarent sur xsl:result-document, ou se rattachent par son attribut format. Un fichier
annexe qui ressort dans un encodage inattendu vient presque toujours de là — le mécanisme est
détaillé dans choisir l'encodage de sortie d'un XSLT.
⚠️ L'écriture est immédiate, la transformation ne l'est pas. Une transformation qui échoue à mi-course laisse les fichiers déjà écrits sur le disque. Il n'y a pas de transaction : après un échec, le répertoire de sortie contient un résultat partiel qui ressemble à un résultat.
Quand aucun fichier n'est écrit du tout
Le symptôme est différent, et la cause aussi : si Saxon ne se plaint de rien et qu'il ne sort
rien, l'instruction n'a jamais été atteinte. Le xsl:result-document est dans un modèle qui ne
s'applique pas, ou dans une branche jamais prise. C'est le même diagnostic que
les cinq causes silencieuses d'un XSLT vide, et il se tranche en
un passage : un point d'arrêt sur le modèle qui contient l'instruction dit en une exécution si
elle est atteinte.
Ce que cet article ne couvre pas
- le mode flux (
streaming), où les contraintes surxsl:result-documentsont bien plus strictes et méritent leur propre traitement ; - la validation des documents produits, qui est un sujet de schéma et non de sortie ;
- les collections en entrée — écrire n fichiers depuis un document est le cas traité ici, en lire n est l'autre moitié du problème.
Le chapitre transformer et exporter du manuel décrit ce que l'application exige des feuilles produisant plusieurs fichiers, et où se règle la destination.