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é avecid,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 :
| Composante | Valeur dans l’exemple | Role |
|---|---|---|
| Code de la règle | BR-CO-10 | Identifiant unique de la règle Schematron |
| Sévérité | fatal | Niveau de gravité (bloquant ou informatif) |
| Message humain | Invoice 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éfixe | Famille | Signification concrète |
|---|---|---|
BR- | Règles de base / générales | BR- 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étique | Un calcul entre totaux ne tombe pas juste |
BR-CL- | Code lists | Un code (devise, pays, unité) n’est pas dans la liste autorisée |
BR-S- | TVA Standard rated | Violation des règles TVA pour la catégorie S |
BR-Z- | TVA Zero rated | Violation des règles TVA pour la catégorie Z |
BR-E- | TVA Exempt | Violation des règles TVA pour la catégorie E |
BR-AE- | TVA Reverse charge | Violation des règles TVA pour la catégorie AE |
BR-IC- | TVA Intra-community | Violation des règles TVA pour la catégorie IC |
BR-O- | TVA Out of scope | Violation des règles TVA pour la catégorie O |
BR-DE- | CIUS allemande | Extension 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-15au lieu de20240115dans un<udt:DateTimeString format="102">— corrigé par la règle de réparation R001 - Virgule décimale :
1234,56au lieu de1234.56dans 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:IDdansExchangedDocument) - BR-05 : code devise absent (
ram:InvoiceCurrencyCodedansHeaderTradeSettlement) - BR-06 : nom du vendeur absent (
ram:NamedansSellerTradeParty) - BR-08 : nom de l’acheteur absent (
ram:NamedansBuyerTradeParty)
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 :
- Code
BR-simple — champ obligatoire manquant - Message : “An Invoice shall have an Invoice number (BT-1)” — il faut un numéro de facture
- XPath :
ExchangedDocument— chercherram:IDdans ce noeud - Diagnostic : le champ
<ram:ID>est absent ou vide dans<rsm:ExchangedDocument> - Type 3 — ajouter le mapping du numéro de facture dans le générateur
Erreur 2 — BR-CL-24 :
- Code
BR-CL-— problème de code list - Message : “Currency code must be according to ISO 4217:2005” — la devise n’est pas reconnue
- XPath :
ApplicableHeaderTradeSettlement— chercherram:InvoiceCurrencyCode - Diagnostic : la valeur est peut-être
EUROau lieu deEUR, ou le champ utilise une virgule décimale qui a été interprétée comme un code devise - Type 1 ou 3 — vérifier la valeur exacte, corriger le mapping ou le format
Erreur 3 — BR-CO-13 :
- Code
BR-CO-— cohérence arithmétique - Message : “BT-112 = BT-109 + BT-110” — le total TTC doit être total HT + total TVA
- XPath :
SpecifiedTradeSettlementHeaderMonetarySummation— les montants sont dans ce noeud - Diagnostic : extraire
ram:GrandTotalAmount(BT-112),ram:TaxBasisTotalAmount(BT-109),ram:TaxTotalAmount(BT-110), et vérifier la formule - 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 :
- Catalogue des erreurs BR-* EN16931 — la référence de chaque règle avec XML invalide, XML corrigé, et pièges à éviter
- Valider EN16931/Factur-X : XSD vs Schematron — comprendre les deux niveaux de validation et leur articulation
- Corriger automatiquement un XML CII invalide — les erreurs de format réparables par l’API
- Champs obligatoires EN16931 : cartographie et mapping ERP — la correspondance entre Business Terms et champs ERP
- Rejets Chorus Pro : erreurs Factur-X et corrections — quand le rapport d’erreur vient de la plateforme B2G
- Déployer un validateur Factur-X — choisir et configurer son outil de validation