Déboguer · Publié le

Les espaces blancs, ou pourquoi la sortie a changé sans raison

Un fichier source reformaté, et la sortie n'est plus la même. Les nœuds de texte composés uniquement d'espaces sont conservés par défaut, et ils comptent.

Deux documents identiques pour un humain — l'un sur une ligne, l'autre indenté — ne produisent pas la même sortie. L'indentation crée des nœuds de texte entre les éléments, et 🔴 XSLT les conserve par défaut dans le document source.

Rien ne les affiche, rien ne les signale, et ils changent le résultat de tout ce qui compte ou positionne. C'est ce qui rend le symptôme si déroutant : la feuille n'a pas bougé, les données non plus, seul le formatage a changé.

XML
<lignes><ligne id="1"/><ligne id="2"/></lignes>

Ce document contient deux nœuds enfants. Le même, réindenté, en contient cinq : deux éléments et trois nœuds de texte faits d'un saut de ligne et d'espaces.

L'asymétrie que personne n'énonce

🔴 La feuille de style et le document source suivent des règles opposées. Dans la feuille, les nœuds de texte faits uniquement de blancs sont supprimés par défaut — sinon toute feuille indentée cracherait des espaces partout. Dans le source, ils sont gardés.

⚠️ On passe donc ses journées avec une règle en tête, et c'est l'autre qui s'applique au fichier qu'on débogue. xsl:text est l'exception dans la feuille : ce qu'il contient est préservé, y compris un espace seul, et c'est à cela qu'il sert.

Ce que cela casse concrètement

ExpressionSans strip-spaceAvec
count(lignes/node())compte aussi les blancsne compte que les éléments
lignes/node()[1]un nœud de texte videle premier élément
following-sibling::node()[1]le blanc qui suitl'élément suivant
normalize-space(.)masque le symptômesans effet ici

⚠️ La dernière ligne est un piège de correction, pas de diagnostic. normalize-space en sortie fait disparaître ce qu'on voit et laisse la cause : les comptages restent faux partout ailleurs, et le défaut réapparaît au prochain endroit où l'on positionne.

La déclaration, et ce qui la contredit

XSLT
<xsl:strip-space elements="*"/>
<xsl:preserve-space elements="pre code"/>

⚠️ xml:space="preserve" dans le document source l'emporte sur xsl:strip-space. Une feuille correcte peut donc rester sans effet sur un document qui déclare cet attribut, souvent hérité d'un ancêtre lointain. Quand le strip-space « ne marche pas », c'est la première chose à chercher.

Le cas qui revient en chaîne

🔴 indent="yes" produit une sortie que la transformation suivante devra dépouiller. Dans une chaîne à plusieurs étapes, l'indentation ajoutée pour la lisibilité devient une donnée significative à l'étape d'après. Le défaut apparaît alors une étape plus loin que sa cause, ce qui est la configuration la plus coûteuse à diagnostiquer.

La règle qui évite le problème est simple : indent="yes" sur ce qu'un humain lit, jamais sur ce qu'une machine relit.

Voir l'arbre, plutôt que le fichier

Le seul moyen fiable de trancher est de regarder l'arbre tel que le processeur l'a construit, et non le texte tel que l'éditeur l'affiche. Un nœud de texte de trois espaces s'y voit ; dans un éditeur, il n'y a rien à voir.

Quand le comptage est correct mais que le contenu reste vide, la cause est ailleurs — voir une variable XSLT vide : les trois causes qu'on ne voit pas. Et quand la sortie contient du texte nu sans balise, ce sont les règles par défaut qui ont recopié ces mêmes nœuds de texte : les cinq causes silencieuses d'un XSLT vide.

Ce que cet article ne couvre pas

  • la sérialisation HTML, dont les règles de blancs sont celles du navigateur et non celles de XSLT ;
  • les feuilles conscientes du schéma, où un contenu déclaré « éléments seulement » supprime la question à la racine ;
  • les entités et les sauts de ligne normalisés à l'analyse, qui se produisent avant tout ceci.

Le chapitre de référence du manuel donne la liste des instructions concernées et l'effet exact de chacune.

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