Article: Croatia’s 2026 e-invoice rule forces PHP developers to reinvent validation – the tax authority’s Schematron file relies on XSLT 2.0, yet the dominant PHP XSLT engine only speaks XSLT 1.0. The result: most accounting apps can’t run the 62 mandatory business-rule checks without a workaround, and a rejected invoice can halt B2B cash flow.
Why the technical hurdle matters
From 1 January 2026 every B2B transaction in Croatia must be exchanged as an e-Račun that complies with 62 specific validation rules. The Tax Administration publishes those rules as a Schematron file – essentially an XSLT 2.0 stylesheet that flags violations. PHP’s built-in libxslt library, which powers the popular xsltproc and most Composer packages, implements only XSLT 1.0. Without XSLT 2.0 support the Schematron cannot be applied, meaning a PHP-based invoicing system will either produce invoices that the tax portal rejects or will have to call out to another language or service.
Three paths developers can take
| Option | What it entails | Practical downsides |
|---|---|---|
| SaxonC PECL extension | Install the Saxon-C processor as a native PHP extension, then invoke the Schematron directly. | The extension is not part of the typical Composer workflow; building and deploying native binaries across different servers adds complexity. |
| External validation service | Send the XML to a web-service that runs the Schematron on your behalf. | Every invoice now depends on network latency and service availability; a temporary outage can block invoicing entirely. |
| Re-implement the rules in PHP | Translate the 62 Schematron assertions into native PHP code. | Requires upfront effort, but once coded the validator runs locally, integrates cleanly with any PHP stack, and eliminates external dependencies. |
The hidden logic that trips simple implementations
A naïve translation of the Schematron can still miss subtle semantics. Take rule HR-BR-4: “A due date must exist if the payable amount is greater than zero.” The Schematron defines a variable that multiplies the invoice amount by –1 for credit notes. In raw XML a credit note shows a positive amount, but the variable flips it negative, so the condition “greater than zero” is false. If the validator only reads the assertion text, it rejects every credit note.
The lesson is clear: read the variable definitions in the Schematron before coding the corresponding PHP condition. The same pattern appears in several other rules where arithmetic or string manipulation hides behind a $ variable.
Common rejection triggers
Even with correctly coded rules, developers often overlook invoice elements that the tax system treats as fatal errors:
- Missing operator details – every invoice must contain the operator’s full name and OIB (Croatian personal identification number). Leaving either field empty triggers an immediate reject.
- Empty XML tags – tags such as
<cbc:Note></cbc:Note>cause the validator to crash. Stripping empty elements or populating them with a placeholder string solves the issue. - Incorrect KPD codes – the Klasifikacija proizvoda i usluga (KPD) code must be at least six digits. Short codes are flagged as malformed.
- Invalid dates – any invoice dated before 1 January 2026 fails the mandatory-date rule, regardless of other correctness.
Testing pitfalls
The Tax Administration publishes sample e-Račun files for developers. Those examples still contain 2025 dates and OIBs that do not pass the 2026 rule set. Using them as the sole source of truth gives a false sense of compliance. Treat the official samples as a parser sanity check, then run your own rule-enforcement suite against realistic data generated by your application.
The PHP-only solution that’s already in the wild
One developer took the re-implementation route to completion, packaging all 62 validation rules as a Composer-installable library for Laravel projects. The library handles the arithmetic, variable scoping, and edge-case checks that the Schematron hides, allowing invoices to be validated entirely within the PHP runtime. By eliminating XSLT 2.0 and external calls, the package offers a deterministic, low-latency path to compliance.
The source code and usage guide are available at the author’s public repository (link provided in the original post).
What to watch next
- ולידטורים של PHP מונעי קהילה – ככל שיותר מפתחים מאמצים את גישת המימוש מחדש, ניתן לצפות ל-forks ולהרחבות שיוסיפו unit-test fixtures, תמיכה בפריימוורקים אחרים או שיפורי ביצועים.
שורה תחתונה
חובת החשבוניות האלקטרוניות של קרואטיה לשנת 2026 מאלצת מפתחי PHP להתמודד עם חוסר התאמה בין Schematron מודרני של XSLT 2.0 לבין מנוע ה-XSLT 1.0 הישן של השפה. תרגום 62 חוקי העסקים ל-PHP native, מעקב אחר לוגיקת משתנים נסתרים והימנעות ממלכודות XML נפוצות, שומרים על תהליך החיוב בתוך הארגון (in-house), עוקפים תקלות הקשורות לרשת, ומכינים את תוכנת הנהלת החשבונות להטמעה חלקה ותקנית עם הגעת המועד האחרון.
