XRechnung · CII · rule diff

XRechnung 2.3.0: CII validation rule changes

33 rules changed between 2.2.0 and 2.3.0 — added, removed, or rewritten. This is computed from the two rule sets directly, not from a changelog.

About this comparison

Revalidate compares the archived 2.2.0 and 2.3.0 rule sets at the assertion and variable level. The diff identifies changed rules; replaying your invoices shows which changes affect your documents.

Browse archived rule sets and checksums. Report published by Revalidate on .

What changed

BR-DE-18Dependency changed

$XR-SKONTO-REGEX now includes a CRLF alternative before "#"

Why this matters

The test expression for the rule is byte-identical between the published versions. The only change is to the variable "$XR-SKONTO-REGEX". Its before value is "#(SKONTO)#TAGE=([0-9]+#PROZENT=[0-9]+\.[0-9]{2})(#BASISBETRAG=-?[0-9]+\.[0-9]{2})?#$", and its after value is "(^|\r?\n)#(SKONTO)#TAGE=([0-9]+#PROZENT=[0-9]+\.[0-9]{2})(#BASISBETRAG=-?[0-9]+\.[0-9]{2})?#$". The change adds a leading alternative for start-of-input or CRLF.

fatalcountry

Original rule text: [BR-DE-18] Skonto Zeilen in muessen diesem regulärem Ausdruck entsprechen: . Die Informationen zur Gewährung von Skonto müssen wie folgt im Element "Payment terms" (BT-20) übermittelt werden: Anzugeben ist im ersten Segment "SKONTO", im zweiten "TAGE=n", im dritten "PROZENT=n". Prozentzahlen sind ohne Vorzeichen sowie mit Punkt getrennt von zwei Nachkommastellen anzugeben. Liegt dem zu berechnenden Betrag nicht BT-115, "fälliger Betrag" zugrunde, sondern nur ein Teil des fälligen Betrags der Rechnung, ist der Grundwert zur Berechnung von Skonto als viertes Segment "BASISBETRAG=n" gemäß dem semantischen Datentypen Amount anzugeben. Jeder Eintrag beginnt mit einer #, die Segmente sind mit einer # getrennt und eine Zeile schließt mit einer # ab. Am Ende einer vollständigen Skontoangabe muss ein XML-konformer Zeilenumbruch folgen. Alle Angaben zur Gewährung von Skonto müssen in Großbuchstaben gemacht werden. Zusätzliches Whitespace (Leerzeichen, Tabulatoren oder Zeilenumbrüche) ist nicht zulässig. Andere Zeichen oder Texte als in den oberen Vorgaben genannt sind nicht zulässig.

Explanation and fix

What this rule requires

This fatal rule checks ram:SpecifiedTradePaymentTerms/ram:Description (BT-20). Every line in that text that begins with # must match the discount pattern #SKONTO#TAGE=<days>#PROZENT=<percentage>#, optionally extended by #BASISBETRAG=<amount>#, where <days> is one or more digits, <percentage> is digits with a decimal point and exactly two decimal places, and <amount> is an optionally signed decimal amount. The complete text must end with a closing # followed by a newline. The check normalizes whitespace around each line before testing, so only the trimmed line content is compared.

How to fix

Set the payment terms text in ram:SpecifiedTradePaymentTerms/ram:Description so each discount entry is exactly like #SKONTO#TAGE=30#PROZENT=2.00# or, if only part of the amount due is the basis, #SKONTO#TAGE=30#PROZENT=2.00#BASISBETRAG=100.00#. Use all uppercase, no internal spaces or tabs, and end the entry with # followed by a newline. Check every line beginning with # against this pattern.

Guidance on this rule. The original text above is authoritative.

BR-DE-18 rule details

Changed variable $XR-SKONTO-REGEX

Before · 2.2.0

'#(SKONTO)#TAGE=([0-9]+#PROZENT=[0-9]+\.[0-9]{2})(#BASISBETRAG=-?[0-9]+\.[0-9]{2})?#$'

After · 2.3.0

'(^|\r?\n)#(SKONTO)#TAGE=([0-9]+#PROZENT=[0-9]+\.[0-9]{2})(#BASISBETRAG=-?[0-9]+\.[0-9]{2})?#$'
BR-DEX-04Dependency changed

The ISO 6523 ICD code list adds "0231" through "0238"

The rule's test expression is byte-identical between releases, but the variable $ISO-6523-ICD-CODES it depends on has changed. Before, the list ended with "0230". After, eight additional codes are present: "0231", "0232", "0233", "0234", "0235", "0236", "0237", "0238". No other codes in the list were removed.

fatalcountry

Original rule text: [BR-DEX-04] Any scheme identifier in MUST be coded using one of the ISO 6523 ICD list.

Explanation and fix

What this rule requires

The rule requires that a party identification element (cac:PartyIdentification/cbc:ID in UBL or ram:GlobalID in CII) with a schemeID attribute and an XRechnung extension context uses a scheme identifier from the ISO 6523 ICD code list supplied by the rule. In UBL, SEPA is also allowed if the element is inside an AccountingSupplierParty or PayeeParty; in CII only the ISO 6523 ICD codes are accepted. The document fails when the schemeID is not one of those allowed codes or contains internal spaces.

How to fix

Set the schemeID attribute to a code from the rule's ISO-6523-ICD-EXT-CODES list (e.g., 0002, 0060, or 0088) with no internal spaces. In UBL, if the party is the accounting supplier or payee, SEPA is also accepted; in CII only an ISO 6523 ICD code is allowed. If the scheme identifier is not needed for this party identification, remove the schemeID attribute.

Guidance on this rule. The original text above is authoritative.

BR-DEX-04 rule details

Changed variable $ISO-6523-ICD-CODES

Before · 2.2.0

' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 '

After · 2.3.0

' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 0231 0232 0233 0234 0235 0236 0237 0238'
BR-DEX-06Dependency changed

ISO 6523 ICD list extended with codes "0231" to "0238"

The rule's test expression is byte-identical between versions, so the check itself did not change. The variable "$ISO-6523-ICD-CODES" grew: it previously ended at code "0230" and now continues with "0231", "0232", "0233", "0234", "0235", "0236", "0237", and "0238". Those eight additional four-digit codes are now included in the space-delimited list of allowed ISO 6523 ICD codes. The rule still requires a scheme identifier to match one of those listed codes.

fatalcountry

Original rule text: [BR-DEX-06] Any scheme identifier in MUST be coded using one of the ISO 6523 ICD list.

Explanation and fix

What this rule requires

This rule applies to item standard identification identifiers that carry a schemeID and occur in a document using the XRechnung extension. It requires the schemeID attribute, after trimming surrounding whitespace, to contain no internal spaces and to be exactly one of the codes listed in the rule's $ISO-6523-ICD-EXT-CODES (for example 0002, 0088, XR01). It fails if the attribute is empty or whitespace-only, contains spaces inside the value, or is not one of those codes.

How to fix

On the relevant element (cac:StandardItemIdentification/cbc:ID in UBL, ram:SpecifiedTradeProduct/ram:GlobalID in CII), set the schemeID attribute to a single valid ISO 6523 ICD code from the allowed list, without any spaces inside the code. For example, use 0002 or XR01 as appropriate. Ensure only one code is provided; if you currently have multiple codes separated by spaces, keep only the applicable one. If the code you used is not in the list, look up the correct ISO 6523 ICD code for the item identification scheme.

Guidance on this rule. The original text above is authoritative.

BR-DEX-06 rule details

Changed variable $ISO-6523-ICD-CODES

Before · 2.2.0

' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 '

After · 2.3.0

' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 0231 0232 0233 0234 0235 0236 0237 0238'
BR-DEX-07Dependency changed

CEF EAS code list gains "0177" and "0235"

The rule's test expression is byte-identical between the two releases; the change is entirely in the variable $CEF-EAS-CODES. That variable's value gains two entries, "0177" after "0170" and "0235" after "0230", inserted in numeric order among the existing four-digit scheme codes. The rule message still requires an Endpoint Identifier scheme identifier to belong to the CEF EAS code list, so the accepted list is simply wider.

fatalcountry

Original rule text: [BR-DEX-07] Any scheme identifier for an Endpoint Identifier in MUST belong to the CEF EAS code list.

Explanation and fix

What this rule requires

For an endpoint identifier (cbc:EndpointID or ram:URIID) that has a schemeID and the invoice declares itself as an XRechnung extension, the schemeID must be exactly one of the codes from the CEF EAS code list accepted by the rule, with no spaces inside the value. The test fails if the schemeID is empty or whitespace-only, contains an internal space, or is not in the allowed code list.

How to fix

Set the schemeID attribute to a valid CEF EAS code from the rule's list, such as "0088" or "0208". Ensure the value is not empty and does not contain spaces. If the current scheme identifier is not in the list, map it to the appropriate CEF EAS code.

Guidance on this rule. The original text above is authoritative.

BR-DEX-07 rule details

Changed variable $CEF-EAS-CODES

Before · 2.2.0

' 0002 0007 0009 0037 0060 0088 0096 0097 0106 0130 0135 0142 0147 0151 0170 0183 0184 0188 0190 0191 0192 0193 0194 0195 0196 0198 0199 0200 0201 0202 0203 0204 0205 0208 0209 0210 0211 0212 0213 0215 0216 0217 0218 0219 0220 0221 0225 0230 9901 9910 9913 9914 9915 9918 9919 9920 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9957 9959 AN AQ AS AU EM '

After · 2.3.0

' 0002 0007 0009 0037 0060 0088 0096 0097 0106 0130 0135 0142 0147 0151 0170 0177 0183 0184 0188 0190 0191 0192 0193 0194 0195 0196 0198 0199 0200 0201 0202 0203 0204 0205 0208 0209 0210 0211 0212 0213 0215 0216 0217 0218 0219 0220 0221 0225 0230 0235 9901 9910 9913 9914 9915 9918 9919 9920 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9957 9959 AN AQ AS AU EM '
BR-DEX-05Dependency changed

The ISO 6523 code list variable now adds "0231" through "0238".

The test expression is byte-identical in both releases, still referencing $ISO-6523-ICD-EXT-CODES. The changed dependency listed is $ISO-6523-ICD-CODES. Its value before ended with "0230"; after it adds "0231", "0232", "0233", "0234", "0235", "0236", "0237", and "0238".

fatalcountry

Original rule text: [BR-DEX-05] Any scheme identifier in MUST be coded using one of the ISO 6523 ICD list.

Explanation and fix

What this rule requires

The rule applies when the document is identified as an XRechnung extension (the $isExtension condition is true). For such documents, the @schemeID attribute on cac:PartyLegalEntity/cbc:CompanyID (UBL) or on ram:ID outside ram:SpecifiedTaxRegistration (CII) must be a code from the ISO 6523 ICD list, and it must not contain any whitespace. If the value is empty, contains a space, or is not exactly one of the listed codes, the document fails validation. This is a fatal rule, so the invoice is rejected.

How to fix

Set @schemeID to one of the allowed ISO 6523 ICD codes from the rule's list, for example XR01 or 0002, and ensure there are no spaces. If the current value is not in the list or contains whitespace, replace it with the correct code for your identification scheme.

Guidance on this rule. The original text above is authoritative.

BR-DEX-05 rule details

Changed variable $ISO-6523-ICD-CODES

Before · 2.2.0

' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 '

After · 2.3.0

' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 0231 0232 0233 0234 0235 0236 0237 0238'
BR-DE-28Dependency changed

New email regex permits a dot at the start or end before the @

Why this matters

The test expression is byte-identical in both releases; only the variable "$XR-EMAIL-REGEX" changed. The new value is "^[^@\s]+@([^@.\s]+\.)+[^@.\s]+$", which permits the part before the @ to be any non-empty sequence of characters that are not @ or whitespace, including a dot at the start or end. Domain labels may now contain any character except @, dot, and whitespace, where the previous pattern required alphanumeric characters and only internal hyphens. The rule message says a dot should not stand at the beginning or end, but the new regular expression does not enforce that for the part before the @.

warningcountry

Original rule text: [BR-DE-28] In BT-43 soll genau ein @-Zeichen enthalten sein, welches nicht von einem Leerzeichen, einem Punkt, aber mindestens zwei Zeichen auf beiden Seiten flankiert werden soll. Ein Punkt sollte nicht am Anfang oder am Ende stehen.

Explanation and fix

What this rule requires

This is a warning, so the document is not rejected, but the rule recommends that the supplier contact email in BT-43 (cbc:ElectronicMail in UBL, ram:URIID in CII) have a plausible email shape. The test accepts values with no whitespace, exactly one @, at least one non-whitespace character before @, and after @ a domain that contains at least one dot with at least one non-dot/non-space character before each dot and no dot immediately after @ or at the end. A value fails if it is empty or only whitespace, has no @ or more than one @, contains spaces, or lacks a dotted domain after @ with non-empty labels.

How to fix

Set the email address in BT-43 to a value that contains exactly one @, no spaces, at least one character before @, and a domain after @ like example.com with at least one dot and non-empty labels. Check for hidden whitespace or extra @ characters. If the email looks correct, verify that you are editing the correct cbc:ElectronicMail or ram:URIID element in the supplier contact.

Guidance on this rule. The original text above is authoritative.

BR-DE-28 rule details

Changed variable $XR-EMAIL-REGEX

Before · 2.2.0

'^[a-zA-Z0-9!#\$%&"*+/=?^_`{|}~-]+(\.[a-zA-Z0-9!#\$%&"*+/=?^_`{|}~-]+)*@([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$'

After · 2.3.0

'^[^@\s]+@([^@.\s]+\.)+[^@.\s]+$'
BR-DEX-08Dependency changed

$ISO-6523-ICD-CODES is not referenced by the unchanged test expression

The test expression is byte-identical in both releases and continues to use "$ISO-6523-ICD-EXT-CODES". The changed variable in the evidence is "$ISO-6523-ICD-CODES"; its value gains "0231", "0232", "0233", "0234", "0235", "0236", "0237", and "0238". Because the expression does not reference "$ISO-6523-ICD-CODES", the evidence does not show that the rule's behavior changed.

fatalcountry

Original rule text: [BR-DEX-08] Any scheme identifier for a Delivery location identifier in MUST be coded using one of the ISO 6523 ICD list.

Explanation and fix

What this rule requires

The rule checks the schemeID attribute of the delivery location identifier (UBL: cac:DeliveryLocation/cbc:ID; CII: ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:GlobalID) when the document is declared as an XRechnung extension. The value must not contain internal spaces and must be one of the codes in the rule's ISO 6523 ICD extension list (for example, 0002, 0088, or XR01). The document fails when this attribute contains an internal space or is not one of those listed codes.

How to fix

Change the schemeID value to a code from the ISO 6523 ICD list, such as 0002, 0088, or XR01. Ensure the value has no spaces; if spaces come from data entry, correct the field or mapping to output only the code. Check the source system's configuration for delivery location identifier schemes and align it with the allowed ISO 6523 ICD codes.

Guidance on this rule. The original text above is authoritative.

BR-DEX-08 rule details

Changed variable $ISO-6523-ICD-CODES

Before · 2.2.0

' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 '

After · 2.3.0

' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 0231 0232 0233 0234 0235 0236 0237 0238'
CII-SR-459Severity raised

The rule escalates from warning to fatal.

The rule's severity rises from warning to fatal; its test expression is byte-identical across releases. Documents that previously passed validation while carrying a warning now fail validation. No other change is evidenced.

fatalschema

Original rule text: [CII-SR-459] - SellerTradeParty URIUniversalCommunication should exist maximum once

Explanation and fix

What this rule requires

The rule checks that in ram:ApplicableHeaderTradeAgreement the ram:SellerTradeParty has at most one ram:URIUniversalCommunication child. The test counts these children and requires the count to be <= 1; a count of 0 is allowed. If more than one is present, the document is rejected because the rule is fatal.

How to fix

In the CII invoice, look under /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty and ensure there is no more than one ram:URIUniversalCommunication element. Remove any extra ram:URIUniversalCommunication elements, or configure the producing system to emit only one.

Guidance on this rule. The original text above is authoritative.

CII-SR-459 rule details
Before · 2.2.0warning
After · 2.3.0fatal
CII-SR-460Severity raised

More than one "URIUniversalCommunication" in "BuyerTradeParty" now fails validation

The severity changed from "warning" to "fatal", while the test expression is byte-identical in both releases. The check still requires that each "BuyerTradeParty" has at most one "URIUniversalCommunication". Documents that previously passed validation with a "warning" now fail validation.

fatalschema

Original rule text: [CII-SR-460] - BuyerTradeParty URIUniversalCommunication should exist maximum once

Explanation and fix

What this rule requires

The rule requires that within ram:BuyerTradeParty under ram:ApplicableHeaderTradeAgreement, the element ram:URIUniversalCommunication occurs at most once. An invoice fails if the buyer trade party has more than one ram:URIUniversalCommunication element.

How to fix

Ensure that the ram:BuyerTradeParty element contains no more than one ram:URIUniversalCommunication. Remove any additional occurrences so that only one remains, or none if not needed.

Guidance on this rule. The original text above is authoritative.

CII-SR-460 rule details
Before · 2.2.0warning
After · 2.3.0fatal
BR-DE-17Test expression rewritten

Type codes with surrounding whitespace now match the allowed code list

The type code comparison now applies normalize-space to the type code before checking it against the allowed list. Previously the raw element value was compared directly, so a value with leading or trailing whitespace would fail even if its trimmed content was an allowed code. The allowed code list is unchanged: "326", "380", "384", "389", "381", "875", "876", and "877". A value with leading or trailing whitespace now matches when its trimmed content is one of those codes.

warningcountry

Original rule text: [BR-DE-17] Mit dem Element "Invoice type code" (BT-3) sollen ausschließlich folgende Codes aus der Codeliste UNTDID 1001 übermittelt werden: 326 (Partial invoice), 380 (Commercial invoice), 384 (Corrected invoice), 389 (Self-billed invoice) und 381 (Credit note),875 (Partial construction invoice), 876 (Partial final construction invoice), 877 (Final construction invoice).

Explanation and fix

What this rule requires

This warning checks the document type code (BT-3). In a UBL invoice or credit note, at least one of cbc:InvoiceTypeCode or cbc:CreditNoteTypeCode must contain one of the codes 326, 380, 384, 389, 381, 875, 876 or 877 (UNTDID 1001). In a CII invoice, rsm:ExchangedDocument/ram:TypeCode must contain one of those same codes. Because the severity is warning, the validator reports it but does not reject the document; it recommends using an allowed code.

How to fix

Set the document type code to one of the allowed values: 326, 380, 384, 389, 381, 875, 876 or 877. In UBL, put it in cbc:InvoiceTypeCode (on an invoice) or cbc:CreditNoteTypeCode (on a credit note); if both are present, at least one must have an allowed value. In CII, put it in rsm:ExchangedDocument/ram:TypeCode. Do not use any other code, and do not leave the relevant element empty or only whitespace.

Guidance on this rule. The original text above is authoritative.

BR-DE-17 rule details

Before · 2.2.0

rsm:ExchangedDocument/ram:TypeCode = ('326', '380', '384', '389', '381', '875', '876', '877')

After · 2.3.0

normalize-space(rsm:ExchangedDocument/ram:TypeCode) = ('326', '380', '384', '389', '381', '875', '876', '877')
BR-DE-26Test expression rewritten

Invoice type code check now strips leading and trailing whitespace and compares to the string "384"

The condition previously compared the invoice type code value to the number "384". It now applies normalize-space to the value, which strips leading and trailing whitespace, and compares the result to the string "384". The rest of the condition is unchanged.

warningcountry

Original rule text: [BR-DE-26] Wenn im Element Invoice type code (BT-3) der Code 384 (Corrected invoice) übergeben wird, soll PRECEDING INVOICE REFERENCE BG-3 mind. einmal vorhanden sein.

Explanation and fix

What this rule requires

The rule recommends that if rsm:ExchangedDocument/ram:TypeCode (Invoice type code, BT-3) has the value 384 (Corrected invoice), then at least one rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument (PRECEDING INVOICE REFERENCE, BG-3) must be present. A document triggers this guideline when the type code is 384 and no ram:InvoiceReferencedDocument exists. Because severity is warning, the validator reports this but does not reject the document.

How to fix

If the invoice is a corrected invoice (384), add at least one ram:InvoiceReferencedDocument under ram:ApplicableHeaderTradeSettlement to reference the preceding invoice.

Guidance on this rule. The original text above is authoritative.

BR-DE-26 rule details

Before · 2.2.0

not(rsm:ExchangedDocument/ram:TypeCode = 384) or (rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument)

After · 2.3.0

not(normalize-space(rsm:ExchangedDocument/ram:TypeCode) = '384') or (rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument)
BR-CL-25Test expression rewritten

CEF EAS allowed codes now include "0177" and "0235"

The rule requires the endpoint identifier scheme identifier to belong to the CEF EAS code list. The allowed value list now includes "0177" and "0235". These codes were not present in the previous list.

fatalbusiness

Original rule text: [BR-CL-25]-Endpoint identifier scheme identifier MUST belong to the CEF EAS code list

Explanation and fix

What this rule requires

The rule requires that the endpoint identifier's schemeID attribute (cbc:EndpointID/@schemeID in UBL, ram:URIID/@schemeID in CII) is a value from the CEF EAS code list, and that the value contains no spaces (after surrounding whitespace is removed). The test checks both conditions: it fails if the normalized schemeID contains any space or if it is not one of the listed codes. Because severity is fatal, an invoice with a schemeID that does not satisfy this is rejected.

How to fix

Set the endpoint identifier scheme identifier to a valid CEF EAS code. In UBL, change cbc:EndpointID/@schemeID to one of the allowed codes, e.g. 0088, 9930, or EM. In CII, set ram:URIID/@schemeID similarly. Ensure the value has no spaces within it and matches exactly one code from the list. If you believe the current value is already a scheme identifier, verify it is listed in the rule; only codes in the list are accepted.

Guidance on this rule. The original text above is authoritative.

BR-CL-25 rule details

Before · 2.2.0

((not(contains(normalize-space(@schemeID), ' ')) and contains(' 0002 0007 0009 0037 0060 0088 0096 0097 0106 0130 0135 0142 0147 0151 0170 0183 0184 0188 0190 0191 0192 0193 0194 0195 0196 0198 0199 0200 0201 0202 0203 0204 0205 0208 0209 0210 0211 0212 0213 0215 0216 0217 0218 0219 0220 0221 0225 0230 9901 9910 9913 9914 9915 9918 9919 9920 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9957 9959 AN AQ AS AU EM ', concat(' ', normalize-space(@schemeID), ' '))))

After · 2.3.0

((not(contains(normalize-space(@schemeID), ' ')) and contains(' 0002 0007 0009 0037 0060 0088 0096 0097 0106 0130 0135 0142 0147 0151 0170 0177 0183 0184 0188 0190 0191 0192 0193 0194 0195 0196 0198 0199 0200 0201 0202 0203 0204 0205 0208 0209 0210 0211 0212 0213 0215 0216 0217 0218 0219 0220 0221 0225 0230 0235 9901 9910 9913 9914 9915 9918 9919 9920 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9957 9959 AN AQ AS AU EM ', concat(' ', normalize-space(@schemeID), ' '))))
PEPPOL-EN16931-R046Test expression rewritten

The net price rule now subtracts only the first allowance amount.

The check now compares the item net price with gross price minus only the first allowance amount. Previously the allowance amount was referenced without an explicit first-item index. The rule message is unchanged.

fatalformat

Original rule text: Item net price MUST equal (Gross price - Allowance amount) when gross price is provided.

PEPPOL-EN16931-R046 rule details

Before · 2.2.0

not(ram:ChargeAmount) or xs:decimal(../ram:NetPriceProductTradePrice/ram:ChargeAmount) = xs:decimal(ram:ChargeAmount) - u:decimalOrZero(ram:AppliedTradeAllowanceCharge/ram:ActualAmount)

After · 2.3.0

not(ram:ChargeAmount) or xs:decimal(../ram:NetPriceProductTradePrice/ram:ChargeAmount) = xs:decimal(ram:ChargeAmount) - u:decimalOrZero(ram:AppliedTradeAllowanceCharge/ram:ActualAmount[1])
BR-DE-20Test expression rewritten

Payment type code "59" with leading or trailing whitespace now requires IBAN validation

The condition for requiring IBAN validation changed. Previously the test compared the payment means type code directly to "59", so an exact match with no surrounding whitespace activated the IBAN format and checksum checks. The revised test normalises whitespace around the type code before comparing it, so values such as " 59" or "59 " are now treated as "59" and the IBAN checks are required. The IBAN format and checksum checks themselves are unchanged.

warningcountry

Original rule text: [BR-DE-20] "Debited account identifier" (BT-91) soll eine korrekte IBAN enthalten, wenn in "Payment means type code" (BT-81) mit dem Code 59 SEPA als Zahlungsmittel gefordert wird.

Explanation and fix

What this rule requires

The rule applies when the payment means type code (BT-81) is 59, indicating SEPA. In that case, the debited account identifier (BT-91) must be a valid IBAN. The test is satisfied if the code is not 59; if it is 59, the account identifier is checked for IBAN validity. This is a warning, so the document is not rejected, but the validator recommends a correct IBAN.

How to fix

If PaymentMeansCode / TypeCode is 59, ensure the account identifier in cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID (UBL) or ram:PayerPartyDebtorFinancialAccount/ram:IBANID (CII) is a valid IBAN. If the code is 59 and the IBAN is correct, check that it is formatted as the rule's IBAN check accepts.

Guidance on this rule. The original text above is authoritative.

BR-DE-20 rule details

Before · 2.2.0

not(ram:TypeCode = '59') or matches(normalize-space(replace(ram:PayerPartyDebtorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')), '^[A-Z]{2}[0-9]{2}[a-zA-Z0-9]{0,30}$') and xs:decimal(string-join(for $cp in string-to-codepoints(concat(substring(normalize-space(replace(ram:PayerPartyDebtorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),5),upper-case(substring(normalize-space(replace(ram:PayerPartyDebtorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),1,2)),substring(normalize-space(replace(ram:PayerPartyDebtorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),3,2))) return (if($cp > 64) then string($cp - 55) else string($cp - 48)),'')) mod 97 = 1

After · 2.3.0

not(normalize-space(ram:TypeCode) = '59') or matches(normalize-space(replace(ram:PayerPartyDebtorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')), '^[A-Z]{2}[0-9]{2}[a-zA-Z0-9]{0,30}$') and xs:decimal(string-join(for $cp in string-to-codepoints(concat(substring(normalize-space(replace(ram:PayerPartyDebtorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),5),upper-case(substring(normalize-space(replace(ram:PayerPartyDebtorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),1,2)),substring(normalize-space(replace(ram:PayerPartyDebtorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),3,2))) return (if($cp > 64) then string($cp - 55) else string($cp - 48)),'')) mod 97 = 1
BR-CL-22Test expression rewritten

Three new VATEX codes join the allowed list: "VATEX-EU-144", "VATEX-EU-146-1E", "VATEX-EU-159"

The list of acceptable VATEX scheme identifiers was extended with "VATEX-EU-144", "VATEX-EU-146-1E", and "VATEX-EU-159", inserted between "VATEX-EU-143-1L" and "VATEX-EU-309". The previous version accepted none of the three. All other listed codes remain unchanged, and the surrounding conditions — no spaces in the value and a case-insensitive match after upper-casing — are unchanged.

fatalbusiness

Original rule text: [BR-CL-22]-Tax exemption reason code identifier scheme identifier MUST belong to the CEF VATEX code list

Explanation and fix

What this rule requires

The rule requires the cbc:TaxExemptionReasonCode element (in CII: ram:ExemptionReasonCode) to contain a value that appears in the CEF VATEX code list. The test first checks that the normalized value contains no space, then checks that the uppercase form of the value is present in the list provided by the rule. A document fails if the value contains a space or is not in that list.

How to fix

Set the cbc:TaxExemptionReasonCode (or ram:ExemptionReasonCode) value to one of the codes listed in the rule's CEF VATEX code list, for example VATEX-EU-79-C or VATEX-FR-FRANCHISE. Ensure the value has no spaces; case is ignored by the test, but using the exact uppercase form is safest. If the current value is not in the list, replace it with the correct VAT exemption reason code.

Guidance on this rule. The original text above is authoritative.

BR-CL-22 rule details

Before · 2.2.0

((not(contains(normalize-space(.), ' ')) and contains(' VATEX-EU-79-C VATEX-EU-132 VATEX-EU-132-1A VATEX-EU-132-1B VATEX-EU-132-1C VATEX-EU-132-1D VATEX-EU-132-1E VATEX-EU-132-1F VATEX-EU-132-1G VATEX-EU-132-1H VATEX-EU-132-1I VATEX-EU-132-1J VATEX-EU-132-1K VATEX-EU-132-1L VATEX-EU-132-1M VATEX-EU-132-1N VATEX-EU-132-1O VATEX-EU-132-1P VATEX-EU-132-1Q VATEX-EU-143 VATEX-EU-143-1A VATEX-EU-143-1B VATEX-EU-143-1C VATEX-EU-143-1D VATEX-EU-143-1E VATEX-EU-143-1F VATEX-EU-143-1FA VATEX-EU-143-1G VATEX-EU-143-1H VATEX-EU-143-1I VATEX-EU-143-1J VATEX-EU-143-1K VATEX-EU-143-1L VATEX-EU-309 VATEX-EU-148 VATEX-EU-148-A VATEX-EU-148-B VATEX-EU-148-C VATEX-EU-148-D VATEX-EU-148-E VATEX-EU-148-F VATEX-EU-148-G VATEX-EU-151 VATEX-EU-151-1A VATEX-EU-151-1AA VATEX-EU-151-1B VATEX-EU-151-1C VATEX-EU-151-1D VATEX-EU-151-1E VATEX-EU-G VATEX-EU-O VATEX-EU-IC VATEX-EU-AE VATEX-EU-D VATEX-EU-F VATEX-EU-I VATEX-EU-J VATEX-FR-FRANCHISE VATEX-FR-CNWVAT ', concat(' ', normalize-space(upper-case(.)), ' '))))

After · 2.3.0

((not(contains(normalize-space(.), ' ')) and contains(' VATEX-EU-79-C VATEX-EU-132 VATEX-EU-132-1A VATEX-EU-132-1B VATEX-EU-132-1C VATEX-EU-132-1D VATEX-EU-132-1E VATEX-EU-132-1F VATEX-EU-132-1G VATEX-EU-132-1H VATEX-EU-132-1I VATEX-EU-132-1J VATEX-EU-132-1K VATEX-EU-132-1L VATEX-EU-132-1M VATEX-EU-132-1N VATEX-EU-132-1O VATEX-EU-132-1P VATEX-EU-132-1Q VATEX-EU-143 VATEX-EU-143-1A VATEX-EU-143-1B VATEX-EU-143-1C VATEX-EU-143-1D VATEX-EU-143-1E VATEX-EU-143-1F VATEX-EU-143-1FA VATEX-EU-143-1G VATEX-EU-143-1H VATEX-EU-143-1I VATEX-EU-143-1J VATEX-EU-143-1K VATEX-EU-143-1L VATEX-EU-144 VATEX-EU-146-1E VATEX-EU-159 VATEX-EU-309 VATEX-EU-148 VATEX-EU-148-A VATEX-EU-148-B VATEX-EU-148-C VATEX-EU-148-D VATEX-EU-148-E VATEX-EU-148-F VATEX-EU-148-G VATEX-EU-151 VATEX-EU-151-1A VATEX-EU-151-1AA VATEX-EU-151-1B VATEX-EU-151-1C VATEX-EU-151-1D VATEX-EU-151-1E VATEX-EU-G VATEX-EU-O VATEX-EU-IC VATEX-EU-AE VATEX-EU-D VATEX-EU-F VATEX-EU-I VATEX-EU-J VATEX-FR-FRANCHISE VATEX-FR-CNWVAT ', concat(' ', normalize-space(upper-case(.)), ' '))))
BR-CL-05Test expression rewritten

Currency code list drops "VEF" and adds "VES", "VED", and "ZWG"

The change is confined to the whitespace-separated list of ISO 4217 alpha-3 currency codes inside the test. The before expression includes "VEF" and does not include "VES", "VED", or "ZWG". The after expression removes "VEF" and adds "VES", "VED", and "ZWG". The surrounding condition—no internal spaces and membership in the list—is unchanged.

fatalbusiness

Original rule text: [BR-CL-05]-Tax currency code MUST be coded using ISO code list 4217 alpha-3

Explanation and fix

What this rule requires

The rule requires cbc:TaxCurrencyCode (UBL) or ram:TaxCurrencyCode (CII) to hold an ISO 4217 alpha-3 currency code from the list accepted by BR-CL-05. It passes only when the normalized value is exactly one of the 178 listed codes, for example EUR, USD, or GBP. A document fails if the element is empty, contains only whitespace, has an internal space, or uses a code not on that list.

How to fix

Put a valid ISO 4217 alpha-3 currency code in the tax currency field, such as EUR, USD, or GBP. Ensure the value has no internal spaces (surrounding whitespace is ignored by the rule) and is not empty or only whitespace. Check that the code is present in the BR-CL-05 list; if the current code is something else, replace it with the correct three-letter ISO 4217 code.

Guidance on this rule. The original text above is authoritative.

BR-CL-05 rule details

Before · 2.2.0

((not(contains(normalize-space(.), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRO MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STD SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UZS VEF VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWL ', concat(' ', normalize-space(.), ' '))))

After · 2.3.0

((not(contains(normalize-space(.), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRO MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STD SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UZS VES VED VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWG ZWL ', concat(' ', normalize-space(.), ' '))))
BR-DEC-23Test expression rewritten

The rule now checks the line-level settlement element instead of the settlement element

The test expression's first element changed from "ram:SpecifiedTradeSettlement" to "ram:SpecifiedLineTradeSettlement". The rest of the expression, including the check that the amount has at most two decimal places, is unchanged. This selects the line-level settlement element where it previously selected the settlement element.

fatalcountry

Original rule text: [BR-DEC-23]-The allowed maximum number of decimals for the Invoice line net amount (BT-131) is 2.

Explanation and fix

What this rule requires

The rule requires that the invoice line net amount (BT-131), carried in cac:InvoiceLine/cbc:LineExtensionAmount (or the credit note line equivalent), has no more than two decimal places. The test checks the characters after the decimal point and fails if there are more than two. For example, 100.123 would fail, while 100.12 or 100 would pass.

How to fix

Change the line net amount to a decimal number with at most two decimal places (for example, 100.12 instead of 100.123). Check the system that calculates or enters line amounts to ensure it does not emit more than two decimals.

Guidance on this rule. The original text above is authoritative.

BR-DEC-23 rule details

Before · 2.2.0

string-length(substring-after(ram:SpecifiedTradeSettlement/ram:SpecifiedTradeSettlementLineMonetarySummation/ram:LineTotalAmount,'.'))<=2

After · 2.3.0

string-length(substring-after(ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeSettlementLineMonetarySummation/ram:LineTotalAmount,'.'))<=2
CII-SR-462Test expression rewritten

Due date type code test now counts all occurrences and requires one distinct value

The previous test counted due date type code elements directly under the applicable trade tax and required the count to be at most one. The new test counts all due date type code elements anywhere under the applicable trade tax and accepts either zero occurrences or any number whose count of distinct values is exactly one. The change shifts the check from a direct-child count limit to a distinct-value condition across all occurrences.

fatalschema

Original rule text: [CII-SR-462] - Only one DueDateTypeCode shall be present

Explanation and fix

What this rule requires

In CII, the rule allows either no ram:DueDateTypeCode under any ram:ApplicableTradeTax, or exactly one distinct value for all such ram:DueDateTypeCode elements. A document fails when there are at least two ram:DueDateTypeCode elements with different values.

How to fix

Ensure that all ram:DueDateTypeCode elements under ram:ApplicableTradeTax contain the same value, or remove all of them if no due date type code is needed. If multiple different codes are present, change them to the intended single code according to the relevant code list.

Guidance on this rule. The original text above is authoritative.

CII-SR-462 rule details

Before · 2.2.0

count(ram:ApplicableTradeTax/ram:DueDateTypeCode) <= 1

After · 2.3.0

count(//ram:ApplicableTradeTax/ram:DueDateTypeCode) = 0 or count(distinct-values(//ram:ApplicableTradeTax/ram:DueDateTypeCode)) = 1
BR-CL-10Test expression rewritten

The allowed ISO 6523 ICD code list gains eight new codes: "0231" through "0238"

The test that checks the scheme identifier against the ISO 6523 ICD list was widened: before, the allowed list ended at "0230"; after, it continues through "0238". The eight added codes are "0231", "0232", "0233", "0234", "0235", "0236", "0237", "0238". The condition that the scheme identifier contain no spaces remains unchanged.

fatalbusiness

Original rule text: [BR-CL-10]-Any identifier identification scheme identifier MUST be coded using one of the ISO 6523 ICD list.

Explanation and fix

What this rule requires

The rule requires the @schemeID attribute on the identifier in cac:PartyIdentification/cbc:ID (UBL) or ram:GlobalID (CII, excluding elements under ram:SpecifiedTradeProduct or ram:ShipToTradeParty) to be a code from the ISO 6523 ICD list. For UBL only, the value SEPA is also accepted if the element is within an cac:AccountingSupplierParty or cac:PayeeParty. If the attribute is present but empty or whitespace-only, contains a space, or is not one of the allowed values, the document fails validation.

How to fix

Set @schemeID to a valid ISO 6523 ICD code, for example 0002, 0003, 0088, or any other code from the rule's accepted list. In UBL, if the scheme must be SEPA, use exactly SEPA and ensure the identifier is inside an cac:AccountingSupplierParty or cac:PayeeParty. Check the current value for typos, extra spaces, or a code outside the allowed list.

Guidance on this rule. The original text above is authoritative.

BR-CL-10 rule details

Before · 2.2.0

((not(contains(normalize-space(@schemeID), ' ')) and contains(' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 ', concat(' ', normalize-space(@schemeID), ' '))))

After · 2.3.0

((not(contains(normalize-space(@schemeID), ' ')) and contains(' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 0231 0232 0233 0234 0235 0236 0237 0238 ', concat(' ', normalize-space(@schemeID), ' '))))
BR-CL-11Test expression rewritten

Eight more ISO 6523 ICD codes are accepted: "0231" through "0238"

The list of acceptable ISO 6523 ICD codes in the rule now includes eight additional values: "0231", "0232", "0233", "0234", "0235", "0236", "0237", and "0238". Previously the list ended at "0230"; it now ends at "0238". The rest of the list is unchanged.

fatalbusiness

Original rule text: [BR-CL-11]-Any registration identifier identification scheme identifier MUST be coded using one of the ISO 6523 ICD list.

Explanation and fix

What this rule requires

The rule requires that the @schemeID of cac:PartyLegalEntity/cbc:CompanyID (UBL) or ram:ID outside ram:SpecifiedTaxRegistration (CII) is coded using one of the ISO 6523 ICD identifiers. The test checks that the normalized value contains no spaces and matches one of the four-digit codes listed in the rule. A document fails when the @schemeID is missing, blank, contains spaces, or has a code not present in that list.

How to fix

Set the @schemeID attribute to a valid four-digit code from the ISO 6523 ICD list accepted by the rule, such as 0002 or 0003, without spaces. Check the exact code used against the codes listed in the rule.

Guidance on this rule. The original text above is authoritative.

BR-CL-11 rule details

Before · 2.2.0

((not(contains(normalize-space(@schemeID), ' ')) and contains(' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 ', concat(' ', normalize-space(@schemeID), ' '))))

After · 2.3.0

((not(contains(normalize-space(@schemeID), ' ')) and contains(' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 0231 0232 0233 0234 0235 0236 0237 0238 ', concat(' ', normalize-space(@schemeID), ' '))))
BR-CL-04Test expression rewritten

The rule's accepted currency code list drops "VEF" and adds "VES", "VED", and "ZWG".

The test changed only in the list of three-letter currency codes it accepts. The earlier list included "VEF"; the current list removes it and adds "VES", "VED", and "ZWG". The surrounding condition is unchanged: the value must have no internal space and, when padded with single spaces, be contained in the quoted list. The rule message still says the currency code must be coded using ISO 4217 alpha-3.

fatalbusiness

Original rule text: [BR-CL-04]-Invoice currency code MUST be coded using ISO code list 4217 alpha-3

Explanation and fix

What this rule requires

The rule requires the invoice currency code to be a valid ISO 4217 alpha-3 currency code. It checks that the code contains no spaces and appears in the rule's list of accepted currency codes. A document fails if cbc:DocumentCurrencyCode (UBL) or ram:InvoiceCurrencyCode (CII) is empty, contains whitespace, or is not one of the listed codes.

How to fix

Set the currency code element to a three-letter ISO 4217 code from the list allowed by the rule, for example EUR, USD, or GBP. In UBL use cbc:DocumentCurrencyCode; in CII use ram:InvoiceCurrencyCode. Ensure the value contains no spaces.

Guidance on this rule. The original text above is authoritative.

BR-CL-04 rule details

Before · 2.2.0

((not(contains(normalize-space(.), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRO MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STD SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UZS VEF VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWL ', concat(' ', normalize-space(.), ' '))))

After · 2.3.0

((not(contains(normalize-space(.), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRO MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STD SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UZS VES VED VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWG ZWL ', concat(' ', normalize-space(.), ' '))))
BR-CL-26Test expression rewritten

ISO 6523 ICD code list extended with eight codes, from "0231" to "0238"

The rule's allowed list of ISO 6523 ICD scheme identifiers now ends at "0238" instead of "0230". The extension adds the exact values "0231", "0232", "0233", "0234", "0235", "0236", "0237" and "0238" to the whitespace-padded list used in the contains check. The preceding part of the expression and the requirement that the scheme identifier contain no spaces are unchanged.

fatalbusiness

Original rule text: [BR-CL-26]-Delivery location identifier scheme identifier MUST belong to the ISO 6523 ICD code list

Explanation and fix

What this rule requires

The rule requires that the schemeID attribute on the delivery location identifier (cac:DeliveryLocation/cbc:ID[@schemeID]) be one of the ISO 6523 ICD codes listed in the rule, with no spaces inside the value. The test rejects any value whose normalized form contains a space or is not in the embedded list. Since this is a fatal rule, an invoice with any other schemeID fails validation.

How to fix

Set the schemeID attribute to a code from the ISO 6523 ICD list, for example 0088, and ensure it has no internal spaces or whitespace. If you are unsure which code applies, check the identifier scheme used for the delivery location.

Guidance on this rule. The original text above is authoritative.

BR-CL-26 rule details

Before · 2.2.0

((not(contains(normalize-space(@schemeID), ' ')) and contains(' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 ', concat(' ', normalize-space(@schemeID), ' '))))

After · 2.3.0

((not(contains(normalize-space(@schemeID), ' ')) and contains(' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 0231 0232 0233 0234 0235 0236 0237 0238 ', concat(' ', normalize-space(@schemeID), ' '))))
BR-CL-21Test expression rewritten

The ISO 6523 ICD code list adds entries "0231" through "0238".

The list of allowed scheme identifiers now includes "0231", "0232", "0233", "0234", "0235", "0236", "0237", and "0238". Previously the list ended at "0230"; the rest of the test expression is unchanged.

fatalbusiness

Original rule text: [BR-CL-21]-Item standard identifier scheme identifier MUST belong to the ISO 6523 ICD code list

Explanation and fix

What this rule requires

The rule requires that the scheme identifier in the item standard identifier (cac:StandardItemIdentification/cbc:ID[@schemeID] in UBL, or ram:SpecifiedTradeProduct/ram:GlobalID[@schemeID] in CII) be exactly one code from the ISO 6523 ICD code list. The test checks that the value does not contain a space and matches one of the listed codes such as 0088, 0160, or 0248. Because the severity is fatal, a value that contains a space or is not among the listed codes causes the document to fail validation.

How to fix

Set the @schemeID attribute to a valid ISO 6523 ICD code from the rule's list, with no spaces inside the value. For example, use 0088 if that is the correct scheme for the item identifier. If the current value is not in the list, look up the correct ISO 6523 ICD code for the identifier scheme in use.

Guidance on this rule. The original text above is authoritative.

BR-CL-21 rule details

Before · 2.2.0

((not(contains(normalize-space(@schemeID), ' ')) and contains(' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 ', concat(' ', normalize-space(@schemeID), ' '))))

After · 2.3.0

((not(contains(normalize-space(@schemeID), ' ')) and contains(' 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 0231 0232 0233 0234 0235 0236 0237 0238 ', concat(' ', normalize-space(@schemeID), ' '))))
CII-SR-440Test expression rewritten

"ActualAmount" maximum-once check now counts occurrences at any level

Before, the test counted "ActualAmount" elements only inside an "AppliedTradeAllowanceCharge" under a "GrossPriceProductTradePrice". After, it counts "ActualAmount" elements wherever they occur, so "ActualAmount" elements outside that nested position are now included in the count. The maximum permitted count remains one.

fatalschema

Original rule text: [CII-SR-440] - ActualAmount should exist maximum once

Explanation and fix

What this rule requires

The rule requires that within each //ram:GrossPriceProductTradePrice/ram:AppliedTradeAllowanceCharge element in the CII document, the child element ram:ActualAmount appears at most once. A document fails validation if the count of ram:ActualAmount child elements is greater than 1. Because this is a fatal rule, exceeding this maximum causes the document to fail validation.

How to fix

In the CII XML, locate every ram:GrossPriceProductTradePrice/ram:AppliedTradeAllowanceCharge element and ensure it contains no more than one ram:ActualAmount child. If multiple ram:ActualAmount elements are present, remove all but one or restructure the data so that only one actual amount is included per AppliedTradeAllowanceCharge. The rule does not specify which value to keep, so choose the correct one based on the intended business data.

Guidance on this rule. The original text above is authoritative.

CII-SR-440 rule details

Before · 2.2.0

count(ram:GrossPriceProductTradePrice/ram:AppliedTradeAllowanceCharge/ram:ActualAmount) <= 1

After · 2.3.0

count(ram:ActualAmount) <= 1
BR-DE-16Test expression rewritten

Seller tax scheme identifiers are now trimmed before matching "VA" or "FC".

The scheme identifier on the seller's tax registration is now whitespace-normalized before being compared with "VA" or "FC". Previously the raw value was compared, so leading or trailing whitespace prevented a match. The change makes the seller tax registration condition accept scheme identifiers with surrounding whitespace. The other parts of the test expression are unchanged.

fatalcountry

Original rule text: [BR-DE-16] Wenn in einer Rechnung die Steuercodes S, Z, E, AE, K, G, L oder M verwendet werden, muss mindestens eines der Elemente "Seller VAT identifier" (BT-31), "Seller tax registration identifier" (BT-32) oder "SELLER TAX REPRESENTATIVE PARTY" (BG-11) übermittelt werden.

Explanation and fix

What this rule requires

BR-DE-16 requires that when the invoice uses VAT category code S, Z, E, AE, K, G, L or M in a document-level allowance, a document-level charge, or an invoice line, at least one of the Seller VAT identifier (BT-31), Seller tax registration identifier (BT-32), or a SELLER TAX REPRESENTATIVE PARTY (BG-11) must be present. In the UBL test, for a document with such a tax code, the condition is satisfied if either cac:TaxRepresentativeParty exists or cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID has non-empty content; the test does not require a particular @schemeID. If none of those tax codes appears, the rule passes.

How to fix

Add one of the following to the invoice: a cac:TaxRepresentativeParty element with the representative's details, or a non-empty cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID (e.g. the seller's VAT or tax registration number). If a tax category code S, Z, E, AE, K, G, L or M is not actually intended, verify and correct that tax category code; otherwise the rule will continue to require one of these seller identification elements.

Guidance on this rule. The original text above is authoritative.

BR-DE-16 rule details

Before · 2.2.0

not((rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:TypeCode = 'VAT' and rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:CategoryCode = ('S', 'Z', 'E', 'AE', 'K', 'G', 'L', 'M')) or (rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax = 'VAT' and rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:CategoryCode = ('S', 'Z', 'E', 'AE', 'K', 'G', 'L', 'M')) or (rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:TypeCode = 'VAT' and rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:CategoryCode = ('S', 'Z', 'E', 'AE', 'K', 'G', 'L', 'M'))) or ((rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID='VA' or @schemeID='FC'][boolean(normalize-space(.))], rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty))

After · 2.3.0

not((rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:TypeCode = 'VAT' and rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:CategoryCode = ('S', 'Z', 'E', 'AE', 'K', 'G', 'L', 'M')) or (rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax = 'VAT' and rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:CategoryCode = ('S', 'Z', 'E', 'AE', 'K', 'G', 'L', 'M')) or (rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:TypeCode = 'VAT' and rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:CategoryCode = ('S', 'Z', 'E', 'AE', 'K', 'G', 'L', 'M'))) or ((rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[normalize-space(@schemeID)='VA' or normalize-space(@schemeID)='FC'][boolean(normalize-space(.))], rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty))
BR-CL-03Test expression rewritten

The currency list removes "VEF" and adds "VES", "VED", and "ZWG".

The test expression checks the currency identifier against an exact currency code list. Compared with published 2.2.0, the 2.3.0 list removes "VEF" and adds "VES", "VED", and "ZWG"; no other entries change. A currency identifier of "VEF" no longer passes, while "VES", "VED", and "ZWG" now do. The rule's stated message still requires the currency identifier to use ISO code list 4217 alpha-3.

fatalbusiness

Original rule text: [BR-CL-03]-currencyID MUST be coded using ISO code list 4217 alpha-3

Explanation and fix

What this rule requires

The rule requires that the @currencyID attribute on amount elements (UBL) or on ram:TaxTotalAmount (CII) contains an ISO 4217 alpha-3 currency code from the list accepted by the rule, and that the code contains no spaces. Because the severity is fatal, an invoice that does not satisfy this condition is rejected with message [BR-CL-03]-currencyID MUST be coded using ISO code list 4217 alpha-3.

How to fix

Set the currencyID attribute to a valid three-letter ISO 4217 alpha-3 code that appears in the rule's list, for example EUR or USD. Ensure the value is not empty and contains no spaces. In UBL this applies to amount elements such as cbc:TaxAmount; in CII it applies to ram:TaxTotalAmount[@currencyID]. If the current value is not a valid code, correct it in the source system.

Guidance on this rule. The original text above is authoritative.

BR-CL-03 rule details

Before · 2.2.0

((not(contains(normalize-space(@currencyID), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRO MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STD SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UZS VEF VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWL ', concat(' ', normalize-space(@currencyID), ' '))))

After · 2.3.0

((not(contains(normalize-space(@currencyID), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRO MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STD SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UZS VES VED VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWG ZWL ', concat(' ', normalize-space(@currencyID), ' '))))
BR-DE-19Test expression rewritten

Whitespace around payment means type code no longer bypasses IBAN check

The test now normalizes whitespace in the payment means type code before comparing it with "58". Previously the comparison was against the raw value, so leading or trailing whitespace made the value not equal to "58" and the IBAN validation was skipped. With the change, such whitespace is stripped and collapsed, so the code is treated as "58" and the IBAN check is applied. The rest of the expression, including the IBAN format and checksum validation, is unchanged.

warningcountry

Original rule text: [BR-DE-19] "Payment account identifier" (BT-84) soll eine korrekte IBAN enthalten, wenn in "Payment means type code" (BT-81) mit dem Code 58 SEPA als Zahlungsmittel gefordert wird.

Explanation and fix

What this rule requires

The rule checks payment means where the payment means code is '30' or '58'. It only requires an IBAN when the code is '58' (SEPA). In that case, the payment account identifier (BT-84) must pass the IBAN validation function xr:checkIBAN. Since the severity is warning, the validator reports this but does not reject the document.

How to fix

For UBL: in cac:PaymentMeans with cbc:PaymentMeansCode = 58, provide a syntactically valid IBAN in cac:PayeeFinancialAccount/cbc:ID. For CII: in ram:SpecifiedTradeSettlementPaymentMeans with ram:TypeCode = 58, provide a valid IBAN in ram:PayeePartyCreditorFinancialAccount/ram:IBANID. If the code is 30, no change is needed for this rule. Check the value against the IBAN checksum that xr:checkIBAN applies.

Guidance on this rule. The original text above is authoritative.

BR-DE-19 rule details

Before · 2.2.0

not(ram:TypeCode = '58') or matches(normalize-space(replace(ram:PayeePartyCreditorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')), '^[A-Z]{2}[0-9]{2}[a-zA-Z0-9]{0,30}$') and xs:integer(string-join(for $cp in string-to-codepoints(concat(substring(normalize-space(replace(ram:PayeePartyCreditorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),5),upper-case(substring(normalize-space(replace(ram:PayeePartyCreditorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),1,2)),substring(normalize-space(replace(ram:PayeePartyCreditorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),3,2))) return (if($cp > 64) then string($cp - 55) else string($cp - 48)),'')) mod 97 = 1

After · 2.3.0

not(normalize-space(ram:TypeCode) = '58') or matches(normalize-space(replace(ram:PayeePartyCreditorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')), '^[A-Z]{2}[0-9]{2}[a-zA-Z0-9]{0,30}$') and xs:integer(string-join(for $cp in string-to-codepoints(concat(substring(normalize-space(replace(ram:PayeePartyCreditorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),5),upper-case(substring(normalize-space(replace(ram:PayeePartyCreditorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),1,2)),substring(normalize-space(replace(ram:PayeePartyCreditorFinancialAccount/ram:IBANID, '([ \n\r\t\s])', '')),3,2))) return (if($cp > 64) then string($cp - 55) else string($cp - 48)),'')) mod 97 = 1
BR-AG-05Test expression rewritten

The "IPSI" VAT rate test now allows "0", matching its message

The check tests the Invoiced item VAT rate when the Invoiced item VAT category code is "IPSI". The test expression changed from greater than "0" to greater than or equal to "0". The rule message already required "0" or greater than "0", so the test now matches that message.

fatalbusiness

Original rule text: [BR-AG-05]-In an Invoice line (BG-25) where the Invoiced item VAT category code (BT-151) is "IPSI" the Invoiced item VAT rate (BT-152) shall be 0 (zero) or greater than zero.

Explanation and fix

What this rule requires

The rule requires that for each invoice or credit note line where the item VAT category code is 'M' (the message calls this 'IPSI', but the test and applicability conditions use code 'M') and the tax scheme is VAT, the VAT rate must be 0 or greater. In UBL this is the value of cbc:Percent inside the matching cac:ClassifiedTaxCategory; in CII it is ram:RateApplicablePercent inside the matching ram:ApplicableTradeTax. A document fails if that rate is negative.

How to fix

Set the VAT rate to 0 or any non-negative number: in UBL, change cbc:Percent; in CII, change ram:RateApplicablePercent. Ensure the line's VAT category code is indeed 'M' and the tax scheme is 'VAT'; if the line should not have code 'M', correct the category code instead. Note that despite the message mentioning 'IPSI', the rule only applies to lines with category code 'M'.

Guidance on this rule. The original text above is authoritative.

BR-AG-05 rule details

Before · 2.2.0

ram:RateApplicablePercent > 0

After · 2.3.0

ram:RateApplicablePercent >= 0
CII-DT-0040New rule

New rule disallows the "schemeURI" attribute.

The rule is new in the published 2.3.0 set and was not present in 2.2.0. Its test requires the "schemeURI" attribute to be absent, expressed as "not(@schemeURI)". The rule message states the same: "schemeURI" should not be present.

fatalschema

Original rule text: [CII-DT-004] - schemeURI should not be present

CII-DT-0040 rule details

Added · 2.3.0

not(@schemeURI)
CII-DT-0030New rule

New rule asserts "schemeDataURI" should not be present

A new rule has been added in "published 2.3.0"; no equivalent check was present in "published 2.2.0". Its message states that "schemeDataURI" should not be present. The rule checks that the "schemeDataURI" attribute is absent. The evidence does not state a severity for this rule.

fatalschema

Original rule text: [CII-DT-003] - schemeDataURI should not be present

CII-DT-0030 rule details

Added · 2.3.0

not(@schemeDataURI)
CII-DT-0020New rule

New rule requires "schemeAgencyName" to be absent

The rule set now includes a check that the attribute "schemeAgencyName" is not present. Any occurrence of the attribute violates the rule, and the rule message is "schemeAgencyName should not be present." This check was added between published versions 2.2.0 and 2.3.0.

fatalschema

Original rule text: [CII-DT-002] - schemeAgencyName should not be present

CII-DT-0020 rule details

Added · 2.3.0

not(@schemeAgencyName)
BR-TMP-2New rule

New rule validates external document location URL format

A rule was added. The test accepts the external document location identifier when it is absent; otherwise it must match the regular expression stored in the variable $XR-URL-REGEX. The rule message says BT-124 "External document location" must be an absolute URL with a valid scheme.

warningbusiness

Original rule text: [BR-TMP-2] BT-124 "External document location" muss eine absolute URL mit gültigem Schema enthalten.

Explanation and fix

What this rule requires

The rule requires that the external document location (BT-124) contains an absolute URL with a valid scheme. In UBL, the element cbc:URI inside cac:AdditionalDocumentReference/cac:Attachment/cac:ExternalReference must match the pattern ^([a-zA-Z])([a-zA-Z0-9+.-])+:.*: it must start with a letter, followed by one or more characters from letters, digits, +, ., -, then a colon, then any characters. In CII, for the ram:AdditionalReferencedDocument with ram:TypeCode = '916', ram:URIID must either be absent or, if present, match the same pattern. This is a fatal rule, so a present but non-matching value causes the document to fail validation.

How to fix

In UBL, set cbc:URI to a value that matches the pattern, such as https://example.com/doc.pdf. In CII, if ram:URIID is present, set it to a matching absolute URL; if no external document location URI is needed, you may omit ram:URIID.

Guidance on this rule. The original text above is authoritative.

BR-TMP-2 rule details

Added · 2.3.0

not(exists(ram:URIID)) or (matches(ram:URIID, $XR-URL-REGEX))
CII-DT-0010New rule

A new rule requires the "schemeName" attribute to be absent.

The rule is new in this comparison. It checks that the "schemeName" attribute is absent: validation passes only when the attribute is not present. The rule message states that "schemeName" should not be present.

fatalschema

Original rule text: [CII-DT-001] - schemeName should not be present

CII-DT-0010 rule details

Added · 2.3.0

not(@schemeName)

Which of these catch you depends on your invoices.

The rule diff is the same for everyone — what breaks is not. Upload a corpus once and every subsequent release gets replayed against your own invoices, so you see what breaks for you.