Technique

Comprendre les messages Schematron EN16931 : guide de lecture des rapports de validation

11 min de lecture Par FacturX API

Comment lire et interpréter un rapport de validation Schematron EN16931 pour Factur-X. Décoder les codes BR-*, localiser les erreurs XPath, décider entre correction manuelle et automatique.

Comment lire un rapport de validation Schematron EN16931 et localiser l’erreur dans le XML ? Chaque ligne du rapport contient 4 composantes : un code BR-*, une sévérité (fatal/warning), un message explicatif, et un XPath qui pointe vers le nœud fautif. Cet article vous apprend à passer du message au champ à corriger. Pour corriger ensuite : /repair (format) ou correction manuelle (fond). Diagnostic instantané via /validate.

En bref

  • 4 composantes par erreur : code BR-* (ex. BR-CO-10), sévérité (fatal = bloquant), message descriptif en anglais, et XPath CII.
  • Familles de codes : BR- présence, BR-CO- calculs, BR-CL- codes, BR-S/Z/E/AE- TVA par catégorie (voir le catalogue complet).
  • Erreur de format vs erreur de fond : format (date ISO, décimal virgule, namespace manquant) → corrigeable automatiquement par /repair. Fond (mauvaise catégorie TVA, montant incorrect) → correction manuelle dans l’ERP.
  • Endpoint /validate : retourne les erreurs en JSON structuré avec id, message, location (XPath), severity — prêt à parser.
  • Chaque code BR-* a sa fiche détaillée : exemple XML qui déclenche, XML corrigé, correction manuelle, réparable par /repair ? → 22 fiches dans le catalogue.

Vous lancez une validation EN16931 sur un XML CII, et le rapport revient avec une liste de lignes comme celle-ci :

[BR-CO-10][fatal] Invoice total amount without VAT (BT-109) = Sum of Invoice line net amount (BT-106) - Sum of allowances on document level (BT-107) + Sum of charges on document level (BT-108)
Location: /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement

Que signifie chaque partie ? Comment passer de ce message au champ à corriger dans le XML ? Et surtout, comment distinguer une erreur de format corrigeable en deux secondes d’un bug de calcul qui nécessite de revoir le moteur de l’ERP ?

Cet article vous apprend à lire un rapport de validation Schematron. Pas à connaître chaque règle par cœur — pour cela, consultez le catalogue des erreurs BR-* avec ses 22 fiches détaillées. Ici, l’objectif est de vous rendre autonome face à n’importe quel rapport, quelle que soit la règle déclenchée.

Pour comprendre la différence entre validation XSD et Schematron et le workflow global, voir Valider EN16931/Factur-X : XSD vs Schematron, erreurs BR-*.

Anatomie d’un message Schematron

Prenons un message réel et décomposons-le pièce par pièce :

[BR-CO-10][fatal]
Invoice total amount without VAT (BT-109) = Sum of Invoice line net amount
(BT-106) - Sum of allowances on document level (BT-107) + Sum of charges
on document level (BT-108)
Location: /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/
  ram:ApplicableHeaderTradeSettlement

Ce message contient quatre composantes distinctes, toujours dans le même ordre :

ComposanteValeur dans l’exempleRole
Code de la règleBR-CO-10Identifiant unique de la règle Schematron
SévéritéfatalNiveau de gravité (bloquant ou informatif)
Message humainInvoice total amount without VAT...Description de ce qui est attendu
Localisation XPath/rsm:CrossIndustryInvoice/rsm:Supply...Chemin vers le noeud XML concerné

Le format exact varie selon le validateur utilisé (KoSIT Validator, Saxon, API FacturX). Le KoSIT produit un SVRL (Schematron Validation Report Language) en XML avec des éléments <svrl:failed-assert>. Saxon produit un rapport similaire. L’API FacturX retourne un JSON structuré avec les mêmes informations mais sous une forme plus exploitable programmatiquement. Les quatre composantes sont toujours présentes, mais leur présentation diffère. Note : veraPDF valide la conformité PDF/A, pas les règles Schematron EN16931.

Les quatre composantes en détail

Le code de la règle (BR-xx)

Le code identifie la règle de manière unique dans le standard EN16931. Le préfixe révèle immédiatement la famille de la règle et donc la nature du problème :

PréfixeFamilleSignification concrète
BR-Règles de base / généralesBR- désigne les règles de base du noyau EN16931. Beaucoup portent sur la présence de champs obligatoires, mais certaines couvrent d’autres contraintes fondamentales
BR-CO-Cohérence arithmétiqueUn calcul entre totaux ne tombe pas juste
BR-CL-Code listsUn code (devise, pays, unité) n’est pas dans la liste autorisée
BR-S-TVA Standard ratedViolation des règles TVA pour la catégorie S
BR-Z-TVA Zero ratedViolation des règles TVA pour la catégorie Z
BR-E-TVA ExemptViolation des règles TVA pour la catégorie E
BR-AE-TVA Reverse chargeViolation des règles TVA pour la catégorie AE
BR-IC-TVA Intra-communityViolation des règles TVA pour la catégorie IC
BR-O-TVA Out of scopeViolation des règles TVA pour la catégorie O
BR-DE-CIUS allemandeExtension nationale XRechnung (hors périmètre FR)

Ce tableau est le premier réflexe de diagnostic : avant même de lire le message, le préfixe vous dit dans quelle direction chercher. Un BR-CO- ? C’est un problème de calcul. Un BR-CL- ? Vérifiez vos codes. Un BR- simple ? Il manque un champ.

La sévérité

Deux niveaux existent dans les artefacts Schematron EN16931 :

  • fatal — l’erreur est bloquante. Le document n’est pas conforme EN16931. Une PDP le rejettera.
  • warning — l’erreur est informative. Le document peut être accepté, mais une anomalie a été détectée.

En pratique, la grande majorité des règles BR-* du noyau EN16931 sont fatal. Les warning apparaissent principalement dans les extensions nationales (CIUS) ou dans certains contrôles additionnels hors noyau. Si votre rapport ne contient que des warning, le document est techniquement conforme — mais les corriger reste recommandé.

Le message humain

Le message est toujours en anglais (c’est la langue du standard CEN). Il décrit ce que la règle attend, pas ce qu’elle a trouvé. C’est une distinction importante : le message dit “Invoice total amount without VAT (BT-109) = Sum of…” — il énonce la formule qui devrait être vraie, pas “votre BT-109 vaut 1000 au lieu de 950”.

Les messages contiennent systématiquement les Business Terms (BT-xxx) concernés. Ces identifiants sont la clé de correspondance avec le standard EN16931 et permettent de retrouver le champ exact dans la cartographie. Pour le mapping entre Business Terms et champs ERP, voir Champs obligatoires EN16931 : cartographie et mapping ERP.

La localisation XPath

Le XPath pointe vers le noeud XML sur lequel la règle s’est déclenchée. En CII (Factur-X), les chemins suivent la structure du standard UN/CEFACT :

/rsm:CrossIndustryInvoice
  /rsm:SupplyChainTradeTransaction
    /ram:ApplicableHeaderTradeSettlement
      /ram:SpecifiedTradeSettlementHeaderMonetarySummation

Attention : le XPath du rapport pointe souvent vers le parent du champ en erreur, pas vers le champ lui-même. C’est parce que la règle Schematron est définie avec un context (le parent) et un test (l’assertion sur un enfant ou une combinaison d’enfants).

Exemple concret : la règle BR-02 (numéro de facture obligatoire) a comme contexte /rsm:CrossIndustryInvoice/rsm:ExchangedDocument. Le XPath du rapport pointe vers ExchangedDocument, mais le champ manquant est ram:ID à l’intérieur de ce noeud.

Comment localiser l’erreur dans le XML

Le XPath du rapport est votre point d’entrée. Voici la procédure systématique :

Étape 1 — Copier le XPath du rapport. Il ressemble à /rsm:CrossIndustryInvoice/rsm:ExchangedDocument ou à un chemin plus profond vers ram:ApplicableHeaderTradeSettlement.

Étape 2 — Ouvrir le XML et naviguer au noeud. Trois méthodes selon votre environnement :

  • VS Code + XML Tools : Ctrl+Shift+P > “XML Tools: Evaluate XPath” > coller le XPath
  • xmllint en ligne de commande (note : cette commande nécessite une gestion correcte des namespaces CII. En pratique, un éditeur XML avec navigation XPath — VS Code + XML Tools — est souvent plus fiable pour le diagnostic) :
    xmllint --xpath "/rsm:CrossIndustryInvoice/rsm:ExchangedDocument" \
      --namespace rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" \
      --namespace ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" \
      facture.xml
  • Recherche manuelle : suivre le chemin segment par segment dans le fichier

Étape 3 — Identifier le champ en erreur dans le noeud. Puisque le XPath pointe vers le parent, il faut lire le message pour savoir quel enfant est concerné. Le message mentionne un Business Term (BT-xxx) — recherchez le champ CII correspondant dans le noeud.

Étape 4 — Vérifier la valeur. Le champ est-il absent, vide, ou contient-il une valeur non conforme ? La réponse détermine l’action corrective.

Les trois types d’erreur et comment réagir

Toute erreur Schematron EN16931 tombe dans l’une de ces trois catégories. Les identifier dès la lecture du rapport accélère le diagnostic.

Type 1 : erreur de format (corrigeable automatiquement)

Ces erreurs apparaissent quand le contenu est sémantiquement correct mais encodé dans un format que CII n’accepte pas. Le générateur XML a produit la bonne valeur, mais dans la mauvaise représentation.

Exemples courants :

  • Date ISO au lieu de AAAAMMJJ : 2024-01-15 au lieu de 20240115 dans un <udt:DateTimeString format="102"> — corrigé par la règle de réparation R001
  • Virgule décimale : 1234,56 au lieu de 1234.56 dans un <ram:GrandTotalAmount> — corrigé par R002
  • Namespace manquant : élément racine sans déclaration xmlns:rsm — corrigé par R005
  • SchemeID absent : <ram:ID>12345678901234</ram:ID> au lieu de <ram:ID schemeID="0002">12345678901234</ram:ID> — corrigé par R006

Les codes R001, R002, R005, R006 sont des identifiants internes de l’API FacturX pour ses règles de réparation automatique — ce ne sont pas des codes du standard EN16931.

Comment reconnaître ce type : le message mentionne un format attendu, ou le code BR-CL-* indique un problème de code list qui peut provenir d’un attribut manquant.

Action : appeler l’API de réparation ou corriger le template du générateur XML. Ces erreurs sont systémiques — si une date est au mauvais format, elles le sont toutes.

Type 2 : erreur arithmétique (bug dans le calcul)

Ces erreurs signalent que les totaux du document ne sont pas cohérents entre eux. La formule énoncée dans le message n’est pas vérifiée avec les valeurs présentes dans le XML.

Erreurs typiques :

  • BR-CO-10 : le total HT ne correspond pas à la somme des lignes moins les remises plus les charges
  • BR-CO-13 : le total TTC ne correspond pas au total HT plus le total TVA
  • BR-CO-15 : le montant à payer ne correspond pas au total TTC moins les acomptes

Comment reconnaître ce type : le préfixe est BR-CO- et le message contient une formule arithmétique avec des Business Terms.

Action : ne corrigez pas le XML directement. Refaites le calcul à la main avec les valeurs du XML pour identifier quel terme est incorrect. L’erreur est dans le moteur de calcul de l’ERP, pas dans le fichier — corriger le fichier sans corriger le moteur ne fait que masquer le bug pour cette facture.

<!-- Vérification manuelle pour BR-CO-10 -->
<!-- BT-106 (somme des lignes nettes) : vérifier ram:LineTotalAmount -->
<!-- BT-107 (remises document) : vérifier ram:AllowanceTotalAmount -->
<!-- BT-108 (charges document) : vérifier ram:ChargeTotalAmount -->
<!-- BT-109 (total HT) : vérifier ram:TaxBasisTotalAmount -->
<!-- Attendu : BT-109 = BT-106 - BT-107 + BT-108 -->

Type 3 : champ manquant (mapping incomplet)

Ces erreurs signalent qu’un champ requis par EN16931 est absent ou vide dans le XML. Le générateur n’a tout simplement pas produit l’élément.

Erreurs typiques :

  • BR-02 : numéro de facture absent (ram:ID dans ExchangedDocument)
  • BR-05 : code devise absent (ram:InvoiceCurrencyCode dans HeaderTradeSettlement)
  • BR-06 : nom du vendeur absent (ram:Name dans SellerTradeParty)
  • BR-08 : nom de l’acheteur absent (ram:Name dans BuyerTradeParty)

Comment reconnaître ce type : le préfixe est BR- simple (sans suffixe CO, CL, S, etc.) et le message indique qu’un champ “shall” ou “must” être présent.

Action : ajouter le mapping du champ manquant dans le générateur XML. Vérifier aussi les champs conditionnels : certains deviennent obligatoires selon le contexte (par exemple, les coordonnées bancaires si le mode de paiement est un virement).

Exemple complet de diagnostic

Voici un rapport réaliste avec trois erreurs. Déroulons le processus pour chacune.

[BR-02][fatal] An Invoice shall have an Invoice number (BT-1).
Location: /rsm:CrossIndustryInvoice/rsm:ExchangedDocument

[BR-CL-24][fatal] Currency code must be according to ISO 4217:2005
Location: /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/
  ram:ApplicableHeaderTradeSettlement

[BR-CO-13][fatal] Invoice total amount with VAT (BT-112) = Invoice total
amount without VAT (BT-109) + Invoice total VAT amount (BT-110).
Location: /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/
  ram:ApplicableHeaderTradeSettlement/
  ram:SpecifiedTradeSettlementHeaderMonetarySummation

Erreur 1 — BR-02 :

  1. Code BR- simple — champ obligatoire manquant
  2. Message : “An Invoice shall have an Invoice number (BT-1)” — il faut un numéro de facture
  3. XPath : ExchangedDocument — chercher ram:ID dans ce noeud
  4. Diagnostic : le champ <ram:ID> est absent ou vide dans <rsm:ExchangedDocument>
  5. Type 3 — ajouter le mapping du numéro de facture dans le générateur

Erreur 2 — BR-CL-24 :

  1. Code BR-CL- — problème de code list
  2. Message : “Currency code must be according to ISO 4217:2005” — la devise n’est pas reconnue
  3. XPath : ApplicableHeaderTradeSettlement — chercher ram:InvoiceCurrencyCode
  4. Diagnostic : la valeur est peut-être EURO au lieu de EUR, ou le champ utilise une virgule décimale qui a été interprétée comme un code devise
  5. Type 1 ou 3 — vérifier la valeur exacte, corriger le mapping ou le format

Erreur 3 — BR-CO-13 :

  1. Code BR-CO- — cohérence arithmétique
  2. Message : “BT-112 = BT-109 + BT-110” — le total TTC doit être total HT + total TVA
  3. XPath : SpecifiedTradeSettlementHeaderMonetarySummation — les montants sont dans ce noeud
  4. Diagnostic : extraire ram:GrandTotalAmount (BT-112), ram:TaxBasisTotalAmount (BT-109), ram:TaxTotalAmount (BT-110), et vérifier la formule
  5. Type 2 — corriger le moteur de calcul dans l’ERP

Trois erreurs, trois types différents, trois actions correctives distinctes. Le processus est toujours le même : code, message, XPath, type, action.

L’API comme accélérateur de diagnostic

Un rapport SVRL brut (la sortie native d’un processeur Schematron comme Saxon ou le KoSIT Validator) est un fichier XML verbeux. L’API FacturX retourne les mêmes informations dans un format JSON structuré, directement exploitable dans un pipeline de debug :

curl -X POST https://api.facturxapi.com/api/v1/validate \
  -H "Authorization: Bearer votre-cle-api" \
  -F "file=@facture.pdf" | jq '.errors[] | {code, message, location}'

Chaque erreur est un objet avec les quatre composantes séparées — plus besoin de parser du XML pour extraire un code ou un XPath. Pour les erreurs de format identifiées comme réparables, l’endpoint /repair les corrige automatiquement avec un diff avant/après et une revalidation. Voir Corriger automatiquement un XML CII Factur-X invalide pour le détail des règles de réparation.

Pour comparer les différentes options de validation (KoSIT, Mustangproject, API SaaS) et leurs formats de rapport respectifs, voir Déployer un validateur Factur-X : KoSIT, Mustangproject ou API SaaS.

Aller plus loin

Ce guide vous donne la méthode pour lire n’importe quel rapport Schematron. Pour approfondir chaque aspect :

#schematron #EN16931 #validation #erreurs #rapport #debug #factur-x