IndexMatic³ | Correction de bugs XML/IDML
December 27, 2025 | IndexMatic³ | fr | en
La nouvelle version d'IndexMatic (26-déc-2025) corrige des bugs du module de sortie XML/IDML. L'os sur lequel vous pouviez tomber sous certaines conditions était, soit un message d'erreur XML, soit le figement de la boîte de dialogue lors de la génération de l'index via IDMS dans InDesign.
On ne le dira jamais assez : le format IDML (InDesign Markup Language) est un petit bijou pour tous les experts en « carrosserie » InDesign. Son seul défaut : il repose sur un dialecte légèrement déviant par rapport au XML standard.
Une des fantaisies d'IDML est son encodage des caractères spéciaux propres à InDesign et situés dans l'intervalle 0x03-0x19. Les fichiers IDML/IDMS associent alors des « instructions de traitement XML » (Processing Instructions) de la forme <?ACE n?> à tout caractère spécial de code inférieur à 32. Non documentés dans la spécification Adobe, ces « codes ACE » constituent en fait des pseudo-instructions destinées à représenter les caractères de contrôle normalement prohibés en XML :
| Caractère InDesign | IDMS/IDML | Description |
|---|---|---|
| U+0003 | <?ACE 3?> |
END NESTED STYLE |
| U+0004 | <?ACE 4?> |
FOOTNOTE |
| U+0007 | <?ACE 7?> |
INDENT HERE TAB |
| U+0008 | <?ACE 8?> |
RIGHT INDENT TAB |
| U+0018 | <?ACE 18?> |
AUTO PAGE NUMBER |
| U+0019 | <?ACE 19?> |
SECTION MARKER |
Parmi ces caractères, ceux auxquels les utilisateurs d'IndexMatic pourraient avoir affaire sont la tabulation de retrait à droite (RIGHT INDENT TAB), le retrait jusqu'à ce point (INDENT HERE TAB) et éventuellement la marque de fin de style imbriqué (END NESTED STYLE). En effet, les options de mise en forme des séparateurs ou délimiteurs autorisent de tels éléments. C'est en pareille éventualité que les versions précédentes d'iX³ risquaient de pédaler dans la semoule !
Note technique
Le problème principal est que dans ExtendScript, E4X (ECMAScript pour XML) ne gère pas facilement la génération dynamique de Processing Instructions (PI) dans les objets XML. Par défaut, les PI sont en effet traitées comme des métadonnées et ne sont pas conservées dans la structure de l'objet XML lors de l'analyse. Lorsque sont scrutées des chaînes XML embarquant des PI, ces dernières sont généralement supprimées ou perdues au cours du processus.
Pour la génération dynamique de fichiers IDML avec nos fameux « codes ACE », l'approche la plus fiable consisterait probablement à contourner entièrement les objets XML et à générer le contenu IDML sous forme de chaînes brutes. Cependant, il reste possible de définir XML.ignoreProcessingInstructions sur FALSE afin d'incorporer des PI lors d'un traitement XML… sous réserve de grand soin !
Divers casse-tête peuvent alors se manifester lorsque vous travaillez avec les méthodes usuelles des instances XML. En particulier, l'option booléenne XML.ignoreWhitespace peut perturber la procédure. Typiquement, pour préparer le contenu IDML via XML, on a besoin de désactiver XML.ignoreWhitespace — faute de quoi les espaces de début et de fin seraient perdus. Mais alors, d'autres routines de conversion XML font apparaître des retours à la ligne aux points d'insertion des Processing Instructions !
La seule solution qui m'est apparue assez solide est de former explicitement l'élement <Content> en passant au constructeur XML une chaîne nettoyée à cet effet :
XML.setSettings ({ ignoreProcessingInstructions: false, // required for ACE ignoreWhitespace: false, // keep leading/trailing sp. prettyPrinting: false, }); var s = " foo\x08bar\t"; // <SPACE>foo<RIGHT INDENT TAB>bar<TAB> var t = s.replace('\x08','<?ACE 8?>'); // IDML encoding var x = XML( "<Content>" + t + "</Content>" ); alert( x.toXMLString() ); // `<Content> foo<?ACE 8?>bar\t</Content>`
Note. — Les techniques à base de <Content/>.prependChild(...) — ou les approches similaires qui présupposent un argument XML bien formé — ont provoqué toute une série de problèmes par réaction en chaîne.
Partant de ce principe, on peut alors concevoir une fonction plus générique (et plus sécurisée) assurant la conversion d'une chaîne quelconque vers un élément <Content> prêt à être injecté dans votre flux XML au sein du noeud <CharacterStyleRange> courant :
function idmlContent(/*str*/rawString, re1,rp1,re2,t) //---------------------------------- // Sanitizes rawString for IDML content and return the // XML element `<Content>...</Content>`. // Assumes XML.ignoreProcessingInstructions===false // => XML { // XML escape: < > & re1 = callee.RE_ESC || (callee.RE_ESC=/[<&>]/g); rp1 = callee.RP_ESC || (callee.RP_ESC={'<':'<','&':'&','>':'>'}); // Control characters are illegal in XML except for 0x9, 0xA, 0xD. // IDML then uses the PI scheme `<?ACE hex ?>` re2 = callee.RE_ACES || (callee.RE_ACES=/[\u0001-\u0008\u000B\u000C\u000E-\u001F]/g); t = rawString .replace(re1, function(c){ return rp1[c]} ) .replace(re2, function(c) { return '<?ACE ' + c.charCodeAt(0).toString(16) + '?>'; }); return XML("<Content>" + t + "</Content>"); } // Sample usage XML.setSettings ({ ignoreProcessingInstructions: false, ignoreWhitespace: false, prettyPrinting: false, }); var s = " foo\x08bar\t"; var x = idmlContent(s); // Valid XML <Content> // etc
• V. aussi : Caractères spéciaux d'InDesign