Peppol BIS Billing · ubl · rule diff

What 3.0.21 changed

22 rules changed between 3.0.20 and 3.0.21 — added, removed, or rewritten. This is computed from the two rule sets directly, not from a changelog.

What changed

DE-R-018Behaviour changed without the rule changing
$XR-SKONTO-REGEX: '#(SKONTO)#TAGE=([0-9]+#PROZENT=[0-9]+\.[0-9]{2})(#BASISBETRAG=-?[0-9]+\.[0-9]{2})?#$' → '(^|\r?\n)#(SKONTO)#TAGE=([0-9]+#PROZENT=[0-9]+\.[0-9]{2})(#BASISBETRAG=-?[0-9]+\.[0-9]{2})?#$'

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-EN16931-CL007Behaviour changed without the rule changing
$ISO4217: tokenize('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 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 MRU 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 UYW UZS VED VES VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA YER ZAR ZMW ZWG XXX CNH', '\s') → tokenize('AED AFN ALL AMD AOA ARS AUD AWG AZN BAM BBD BDT BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC 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 MRU 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 STN SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UYW UZS VED VES VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA YER ZAR ZMW ZWG XXX CNH XCG', '\s')

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-EN16931-CL008Behaviour changed without the rule changing
$eaid: tokenize('0002 0007 0009 0037 0060 0088 0096 0097 0106 0130 0135 0142 0151 0177 0183 0184 0188 0190 0191 0192 0193 0195 0196 0198 0199 0200 0201 0202 0204 0208 0209 0210 0211 0212 0213 0215 0216 0218 0221 0230 0235 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 0147 0154 0158 0170 0194 0203 0205 0217 0225 0240 0244 0245 ', '\s') → tokenize('0002 0007 0009 0060 0088 0096 0097 0106 0130 0135 0142 0151 0158 0183 0184 0188 0190 0191 0192 0195 0196 0198 0199 0200 0201 0204 0208 0209 0210 0211 0216 0218 0221 0225 0230 0235 0240 0242 0244 0245 0246 0248 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', '\s')

The change is shown above; an explanation appears once one has been reviewed.

DE-R-028Behaviour changed without the rule changing
$XR-EMAIL-REGEX: '^[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])?$' → '^[^@\s]+@([^@.\s]+\.)+[^@.\s]+$'

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-EN16931-R007Behaviour changed without the rule changing
$profile: if (/*/cbc:ProfileID and matches(normalize-space(/*/cbc:ProfileID), 'urn:fdc:peppol.eu:2017:poacc:billing:([0-9]{2}):1.0')) then tokenize(normalize-space(/*/cbc:ProfileID), ':')[7] else 'Unknown' → if (normalize-space(/*/cbc:ProfileID) = ( 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0', 'urn:peppol:france:billing:regulated', 'urn:peppol:france:billing:non-regulated' )) then '01' else if (normalize-space(/*/cbc:ProfileID) = 'urn:peppol:bis:billing_with_response') then '02' else 'Unknown'

The change is shown above; an explanation appears once one has been reviewed.

DK-R-003Severity raised
severity: warning → fatal

The change is shown above; an explanation appears once one has been reviewed.

DK-R-017Severity raised
severity: warning → fatal

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-COMMON-R052Severity raised
severity: warning → fatal

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-COMMON-R053Severity raised
severity: warning → fatal

The change is shown above; an explanation appears once one has been reviewed.

DE-R-017Test expression rewritten
cbc:InvoiceTypeCode = $supportedInvAndCNTypeCodes or cbc:CreditNoteTypeCode = $supportedInvAndCNTypeCodes
normalize-space(cbc:InvoiceTypeCode) = $supportedInvAndCNTypeCodes or normalize-space(cbc:CreditNoteTypeCode) = $supportedInvAndCNTypeCodes

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-EN16931-P0100Test expression rewritten
$profile != '01' or (some $code in tokenize('71 80 82 84 102 218 219 326 331 380 382 383 384 386 388 393 395 553 575 623 780 817 870 875 876 877', '\s') satisfies normalize-space(text()) = $code)
not($profile = ('01','02')) or (some $code in tokenize('71 80 82 84 102 218 219 326 331 380 382 383 384 386 388 393 395 553 575 623 780 817 870 875 876 877', '\s') satisfies normalize-space(text()) = $code)

The change is shown above; an explanation appears once one has been reviewed.

DE-R-026Test expression rewritten
((not(cbc:InvoiceTypeCode = 384 or cbc:CreditNoteTypeCode = 384) or (cac:BillingReference/cac:InvoiceDocumentReference)))
((not(normalize-space(cbc:InvoiceTypeCode) = '384' or normalize-space(cbc:CreditNoteTypeCode) = '384') or (cac:BillingReference/cac:InvoiceDocumentReference)))

The change is shown above; an explanation appears once one has been reviewed.

DE-R-019Test expression rewritten
not(cbc:PaymentMeansCode = '58') or matches(normalize-space(replace(cac:PayeeFinancialAccount/cbc:ID, '([ \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(cac:PayeeFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),5),upper-case(substring(normalize-space(replace(cac:PayeeFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),1,2)),substring(normalize-space(replace(cac:PayeeFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),3,2))) return (if($cp > 64) then string($cp - 55) else string($cp - 48)),'')) mod 97 = 1
not(normalize-space(cbc:PaymentMeansCode) = '58') or matches(normalize-space(replace(cac:PayeeFinancialAccount/cbc:ID, '([ \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(cac:PayeeFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),5),upper-case(substring(normalize-space(replace(cac:PayeeFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),1,2)),substring(normalize-space(replace(cac:PayeeFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),3,2))) return (if($cp > 64) then string($cp - 55) else string($cp - 48)),'')) mod 97 = 1

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-EN16931-P0101Test expression rewritten
$profile != '01' or (some $code in tokenize('381 396 81 83 532', '\s') satisfies normalize-space(text()) = $code)
not($profile = ('01','02')) or (some $code in tokenize('381 396 81 83 532', '\s') satisfies normalize-space(text()) = $code)

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-EN16931-R004Test expression rewritten
starts-with(normalize-space(cbc:CustomizationID/text()), 'urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0')
starts-with(normalize-space(cbc:CustomizationID/text()), 'urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0') and not(contains(normalize-space(cbc:CustomizationID/text()), '::'))

The change is shown above; an explanation appears once one has been reviewed.

DE-R-020Test expression rewritten
not(cbc:PaymentMeansCode = '59') or matches(normalize-space(replace(cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID, '([ \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(cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),5),upper-case(substring(normalize-space(replace(cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),1,2)),substring(normalize-space(replace(cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),3,2))) return (if($cp > 64) then string($cp - 55) else string($cp - 48)),'')) mod 97 = 1
not(normalize-space(cbc:PaymentMeansCode) = '59') or matches(normalize-space(replace(cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID, '([ \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(cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),5),upper-case(substring(normalize-space(replace(cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),1,2)),substring(normalize-space(replace(cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID, '([ \n\r\t\s])', '')),3,2))) return (if($cp > 64) then string($cp - 55) else string($cp - 48)),'')) mod 97 = 1

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-COMMON-R055New rule
asserts: matches(normalize-space(), '^[0-9]{20}$')

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-COMMON-R056-1New rule
asserts: matches(normalize-space(), '^NL[0-9]{9}B[0-9]{2}$')

The change is shown above; an explanation appears once one has been reviewed.

DE-R-T02New rule
asserts: matches(cbc:URI, $XR-URL-REGEX)

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-COMMON-R056-2New rule
asserts: matches(normalize-space(.), '^NL[0-9]{9}B[0-9]{2}$')

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-COMMON-R054New rule
asserts: matches(normalize-space(), '^[0-9]{8}$')

The change is shown above; an explanation appears once one has been reviewed.

PEPPOL-COMMON-R057New rule
asserts: matches(normalize-space(), '^[0-9]{12}$')

The change is shown above; an explanation appears once one has been reviewed.

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.

RRevalidate

Corpus regression testing for Peppol e-invoices. Rule sets are pulled from docs.peppol.eu, compiled through the ISO Schematron skeleton, and executed with Saxon.

Scope

  • Peppol BIS Billing
  • UBL and CII
  • CEN and Peppol layers

Peppol is a registered trademark of OpenPeppol AISBL. Revalidate is an independent tool and is not affiliated with or endorsed by OpenPeppol. Privacy & data