HotPDF genererer, detekterer og validerer elektroniske ZUGFeRD- og Factur-X-fakturaer fra Delphi og C++Builder. AddFacturXAssociatedFile bygger inn XML-filen for EN 16931-fakturaen i en PDF/A-3-beholder, DetectFacturXInvoice gjenkjenner en innkommende hybridfaktura, og HPDFValidateEInvoice kjører de offisielle forretningsreglene fra EN 16931 Schematron mot den innebygde XML-en. Denne artikkelen går gjennom alle de tre trinnene og er ærlig om hvor valideringsmotoren stopper
Presset bak dette funksjonssettet er regulatorisk, ikke teknisk. Tyskland og Frankrike faser inn obligatorisk strukturert e-fakturering for innenlandske B2B-transaksjoner, og begge mandatene konvergerer mot den samme hybridmodellen: PDF-fakturaen som ERP-systemet ditt allerede produserer, må bære en maskinlesbar XML-tvilling inni seg. En Delphi-regnskaps- eller ERP-applikasjon som sender ut vanlige PDF-fakturaer i dag, har en hard tidsfrist for å begynne å sende ut Factur-X eller ZUGFeRD, og forskjellen mellom de alvorlighetsgradene de to navnene er mindre enn markedsføringen antyder — Factur-X og ZUGFeRD er den samme tysk-franske standarden utgitt under to merkelapper
Hva gjør en PDF til en gyldig Factur-X-faktura?
En gyldig Factur-X-faktura er en PDF/A-3-fil (ISO 19005-3) som bygger inn nøyaktig én strukturert faktura-XML som en tilknyttet fil, lenker til den fra dokumentkatalogen, og deklarerer den i XMP-utvidelsesmetadata. Tre lag må stemme overens. For det første må beholderen samsvare med PDF/A-3, arkivprofilen som — i motsetning til PDF/A-1 og PDF/A-2 — tillater innebygde filer av alle typer. For det andre må faktura-XML-en, kalt factur-x.xml for standardprofiler eller xrechnung.xml for den tyske XRechnung-varianten, registreres i katalogens /AF-tabell og treet /Names /EmbeddedFiles, med en AFRelationship-oppføring som angir hva vedlegget er: Alternative betyr at XML-en er en tilsvarende representasjon av den synlige fakturaen, noe som er semantikken de fleste profiler krever. For det tredje må Factur-X sitt XMP-utvidelsesskjema navngi den innebygde filen, dens samsvarsnivå og dokumenttypen, slik at et mottakssystem kan klassifisere fakturaen uten å analysere XML-en i det hele tatt
Hvorfor ZUGFeRD 2.5 ikke trenger en ny beholder
ZUGFeRD 2.5 endrer ingenting på PDF-beholdernivå: retningslinje-URN-ene, XMP-skjemaet og versjons-tokenet er identiske med ZUGFeRD 2.3 / Factur-X 1.0. Dette overrasker de fleste utviklere, så det er verdt å sitere kilden. Spesifikasjonen for Factur-X 1.09 slår fast at versjonsnummeret i URI-en til PDF/A-utvidelsesskjemaet ikke er relatert til versjonsnummeret til XML-datasesifikasjonen, og at versjoneringen av Factur-X-faktura-instanser forblir 1.0 — både i XMP fx:Version og i BT-24 i factur-x.xml. Det offisielle ZUGFeRD 2.5-eksempelsamlingen bekrefter det: hvert eksempel bygger inn factur-x.xml under en urn:factur-x.eu:1p0 retningslinje-URN med fx:Version satt til 1.0. Det 2.5 faktisk legger til, lever inne i XML-datamodellen — nye elementer som underfakturalinjer og batch-identifikatorer — som er forretningslaget applikasjonen din genererer, ikke beholderlaget PDF-biblioteket administrerer
HotPDF koder dette direkte. AddFacturXAssociatedFile godtar et Version-argument og normaliserer det via HPDFFacturXNormalizeVersion før XMP skrives, slik at en kaller som sender inn 2p5-aliaset fremdeles sender ut det spesifikasjonskompatible tokenet i stedet for å finne opp en 2p5 XMP-versjon som ingen validator ville godtatt. Deteksjonshjelperne behandler 2p5 som likeverdig ved lesing, slik at rundreiser forblir symmetriske. Hvis et bibliotek eller verktøy forteller deg at det skriver en spesiell ZUGFeRD 2.5-beholder, spesifikasjonen selv sier at noe slikt ikke eksisterer
Innbygging av faktura-XML fra Delphi
THotPDF.AddFacturXAssociatedFile gjør en vanlig PDF/A-3-genereringskjøring om til en Factur-X-faktura med ett enkelt kall: den bygger inn XML-bytene som en tilknyttet fil, registrerer factur-x.xml i katalogens /AF-tabell og treet /Names /EmbeddedFiles, og sender ut de tilsvarende Factur-X XMP-utvidelsesmetadataene. Du tegner den menneskelig lesbare fakturasiden med det vanlige canvas-API-et til HotPDF; beholderarbeidet er en enkelt linje mellom BeginDoc og EndDoc
var
Pdf: THotPDF;
InvoiceXML, UBLXML: TBytes;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'invoice-2026-0042.pdf';
Pdf.PDFACompliance := '3B'; // PDF/A-3b container
Pdf.BeginDoc;
// embed the EN 16931 CII invoice XML as factur-x.xml
InvoiceXML := BuildInvoiceXML; // produced by your business layer
Pdf.AddFacturXAssociatedFile(InvoiceXML, 'EN 16931');
// optional: attach a UBL view as a supplementary representation
UBLXML := BuildUBLXML;
Pdf.AddUBLSupplementaryFile(UBLXML); // factur-xubl.xml, Alternative
// ... draw the visible invoice page here ...
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Standardverdiene følger spesifikasjonen: filnavn factur-x.xml, relasjon Alternative, versjon 1.0. AddUBLSupplementaryFile implementerer avsnitt 6.4 i Factur-X 1.09-spesifikasjonen, som tillater at en UBL-representasjon av den samme fakturaen blir med som et andre vedlegg kalt factur-xubl.xml med MIME-type application/xml og relasjonen Alternative. Rekkefølgen har betydning her, og HotPDF håndhever begrensningen spesifikasjonen innebærer: UBL-filen er en oppføring tilknyttet representasjon, og må legges til etter at AddFacturXAssociatedFile har registrert CII-hovedfilen. Merk at den tegnede siden og den innebygde XML-en må oppgi samme faktura — en PDF som viser én sum og koder en annen, er akkurat den feilmodusen hybrid fakturering er utformet for å forhindre. PDF/A-3-siden av denne arbeidsflyten, inkludert OutputIntent og skriftinnbygging, dekkes i mer dybde i den tilhørende artikkelen om PDF/A-, PDF/X- og PDF/UA-validering i Delphi
Hvordan oppdager du en Factur-X-faktura i en innkommende PDF?
THotPDF.DetectFacturXInvoice besvarer den mottakende siden av mandatet: last inn hvilken som helst PDF og finn ut i ett enkelt kall om det er en hybridfaktura, hvilken profil den deklarerer, og hvilke vedlegg den bærer. Funksjonen returnerer en THPDFFacturXInvoiceInfo-post med den innebygde XML-ens filnavn, det XMP-deklarerte dokumentfilnavnet og -typen, versjonstokenet, samsvarsnivået, retningslinje-URN-en og AFRelationship-verdien. To ytterligere felt rapporterer supplerende visninger: UBLFileName fylles ut når et factur-xubl.xml-vedlegg er til stede, og EDIFACTFileName når en EDIFACT-visning følger med — ingen av dem påvirker deteksjonskonklusjonen, fordi en supplerende representasjon ikke kan eksistere uten den primære CII-fakturaen
var
Reader: THotPDF;
Info: THPDFFacturXInvoiceInfo;
begin
Reader := THotPDF.Create(nil);
try
if Reader.LoadFromFile('incoming-invoice.pdf') <= 0 then
raise Exception.Create('No pages loaded.');
if Reader.DetectFacturXInvoice(Info) then
begin
Writeln('Invoice XML: ', string(Info.FileName));
Writeln('Conformance: ', string(Info.ConformanceLevel));
Writeln('Guideline URN: ', string(Info.GuidelineID));
Writeln('Relationship: ', string(Info.AFRelationship));
if Info.UBLFileName <> '' then
Writeln('UBL view: ', string(Info.UBLFileName));
end
else
Writeln('Not a Factur-X / ZUGFeRD hybrid invoice.');
finally
Reader.Free;
end;
end;
Deteksjon leser de samme signalene en kompatibel validator leser — XMP-utvidelsesskjemaet og registeret for tilknyttede filer — snarere enn å gjette ut fra filnavn alene. Det samme lastede dokumentobjektet eksponerer også metadataene i XMP og Info-ordboken for inspeksjon eller korreksjon, en arbeidsflyt som er beskrevet i artikkelen om redigering av metadata i lastede PDF-dokumenter
Forretningsregler eller skjema: hva betyr EN 16931-validering?
HPDFValidateEInvoice, en frittstående funksjon i enheten HPDFEInvoiceValidator, kjører begge valideringslagene i rekkefølge: først sjekken av beholderstruktur via ValidateFacturXInvoice, og deretter forretningsreglene fra EN 16931 Schematron mot den utpakkede faktura-XML-en. HotPDF leveres med de fem offisielle regelfilene for Factur-X 1.09 — MINIMUM, BASIC WL, BASIC, EN 16931 og EXTENDED — under Lib/resources/Schematron/, og HPDFSchematronFileForProfile velger filen som samsvarer med det detekterte samsvarsnivået, slik at en EN 16931-faktura automatisk kontrolleres mot Factur-X_1.09_EN16931.sch. Funksjonen returnerer True bare når beholderen er gyldig og ingen forretningsregel ble utløst
uses HPDFEInvoiceValidator;
var
Reader: THotPDF;
Report: THPDFEInvoiceValidationReport;
I: Integer;
begin
Reader := THotPDF.Create(nil);
try
Reader.LoadFromFile('incoming-invoice.pdf');
if HPDFValidateEInvoice(Reader, SchematronDir, Report) then
Writeln('Container and business rules: OK')
else
Writeln('Validation found issues.');
if Report.BusinessRulesEvaluated then
begin
Writeln(Report.BusinessSummary.Evaluated, ' rules evaluated, ',
Report.BusinessSummary.Skipped, ' skipped (XPath 2.0)');
for I := 0 to High(Report.BusinessRules) do
if (not Report.BusinessRules[I].Skipped) and
(Report.BusinessRules[I].Severity = stsError) then
Writeln(string(Report.BusinessRules[I].RuleID), ': ',
string(Report.BusinessRules[I].Message));
end;
finally
Reader.Free;
end;
end;
Hver oppføring i BusinessRules bærer regelidentifikatoren parset fra påstandsteksten — BR-45, BR-CO-17, og resten av navneskjemaet for EN 16931 — pluss regelkonteksten i XPath, testuttrykket og en alvorlighetsgrad som speiler Schematron-flag-attributtet. Det gjør rapporten praktisk anvendelig: i stedet for et enkelt bestått/ikke-bestått, får du det nøyaktige forretningsbegrepet som er inkonsistent, noe kundestøtteteamet ditt trenger når en kunde spør hvorfor en faktura ble avvist. Team som allerede genererer strukturerte samsvarsrapporter for arkiv-PDF-er, kan legge disse resultatene inn i den samme rørledningen som er beskrevet i artikkelen om automatisering av preflight-rapporter for PDF
Hvor valideringen stopper, ærlig talt
Schematron-motoren er bygd på MSXML, som evaluerer XPath 1.0. EN 16931-regelfilen deklarerer queryBinding="xslt2" og bærer 424 påstander, hvorav de fleste kun bruker XPath 1.0-funksjoner som string-length og substring-after — disse kjører naturlig. Et mindretall stoler på XPath 2.0-konstruksjoner som xs:decimal-konverteringer eller exists(); HotPDF forhåndsskanner hvert testuttrykk for kjente XPath 2.0-tokener og markerer disse reglene som Skipped med alvorlighetsgrad info, i stedet for å forsøke en evaluering som ville slå feil i det stille. Sammendraget rapporterer antall evaluerte og skippede regler hver for seg, slik at loggen din alltid oppgir nøyaktig hvor mye av regelsettet som ble testet. På Delphi 7, der MSXML-bindinger er utilgjengelige, enheten kompilerer en stubb som rapporterer at motoren er utilgjengelig uten å forstyrre beholderkonklusjonen; den fulle motoren krever Delphi XE2 eller nyere
Den andre grensen har enda større betydning. Et grønt resultat fra HPDFValidateEInvoice betyr at beholderstrukturen samsvarer og at ingen av de evaluerte forretningsreglene ble utløst — det er ikke en godkjenning av skattemessig samsvar. Nasjonale utvidelsesregler, mottakerspesifikke krav og de juridiske forpliktelsene rundt fakturainnhold ligger over EN 16931-kjernen og utenfor ethvert bibliotek. Behandle valideringsmotoren som porten som holder strukturelt ødelagte fakturaer unna utboksen din og flagger inkonsistente i innboksen din, kjør en fullstendig XPath 2.0-validator i produksjonslinjen din når sertifisering krever det, og la skatterådgiverne dine eie samsvarsspørsmålet. API-ene for innbygging, deteksjon og validering vist her er en del av den standard HotPDF Component for Delphi og C++Builder, med et komplett eksempelsystem for e-fakturaer som dekker alle de syv ZUGFeRD- og Factur-X-profilene