Izradili ste Factur-X račun i svaka provjera kontejnera prolazi. Katalog nosi /AF niz, imensko stablo EmbeddedFiles razrješuje se do ispravne specifikacije datoteke, ugrađeni factur-x.xml ima ispravan /AFRelationship vrijednosti Alternative, a ugrađeni ValidateFacturXInvoice vraća 1. Zatim pokrenete istu datoteku kroz veraPDF, referentni provjerivač kojeg koriste porezni portali, i on presudi da čitav dokument nije valjani PDF/A-3. Struktura je ispravna. Metapodaci su problem, a ta je pogreška jedna od najlakših u čitavom e-invoice workflowu za previdjeti
Razlog je vrijedno u potpunosti shvatiti, jer objašnjava klasu PDF/A nedostatka koji nema nikakve veze s vidljivom stranicom ili prilogom, a sve veze s time kako XMP opisuje samog sebe. To je zamka koja se krije iza zelene provjere kontejnera
Ta četiri svojstva zbog kojih dokument pada
Factur-X račun zapisuje četiri prilagođena svojstva u svoj XMP paket kako bi nizvodni softver mogao pročitati profil tog računa bez parsiranja samog ugrađenog XML-a. Ona žive u Factur-X prostoru imena pod prefiksom fx: fx:DocumentFileName, fx:DocumentType, fx:Version, i fx:ConformanceLevel. To su upravo oni metapodaci koje čitač treba kako bi znao da taj PDF nosi EN 16931 račun naziva factur-x.xml na verziji 1.0
Nijedno od tih četiri svojstva nije dio neke XMP sheme koju PDF/A unaprijed definira. Dublin Core, XMP Basic, PDF, i PDF/A identifikacijske sheme poznate su sukladnom čitaču, ali fx: nije. Kad veraPDF prošeće tim XMP-om i naiđe na svojstvo čiji prostor imena ne prepoznaje, traži deklaraciju koja bi mu objasnila što to svojstvo znači. Ako takva deklaracija nedostaje, prijavljuje pad protiv ISO 19005-3 klauzule 6.6.2.3.1, koja zahtijeva da se svako svojstvo koje nije izvučeno iz unaprijed definirane sheme opiše u PDF/A shemi proširenja. Četiri neprijavljena svojstva, četiri načina na koje datoteka može biti odbačena, a niti jedno od njih nije vidljivo jednoj čistoj provjeri kontejnera
Zašto PDF/A odbija golo prilagođeno svojstvo
To pravilo zvuči pedantno sve dok se ne sjetite čemu PDF/A uopće služi. Ovaj format postoji kako bi se datoteka mogla otvoriti i posve shvatiti i desetljećima od danas, od softvera kojemu nikad nije bilo rečeno ništa o konvencijama iz 2026. Od sukladnog čitača se očekuje da razluči smisao samog dokumenta, bez ikakvog vanjskog registra za konzultiranje
Prilagođeni metapodaci krše to obećanje osim ako datoteka sa sobom ne nosi vlastiti opis. S obzirom na golo svojstvo fx:ConformanceLevel, budući čitač ne može znati URI prostora imena uz koji se prefiks fx veže, ne može znati je li ta vrijednost tekst, datum ili cijeli broj, i ne može znati opisuje li to svojstvo dotični dokument ili neki vanjski resurs. Mehanizam PDF/A shema proširenja zatvara tu prazninu. On datoteci omogućuje da unutar fiksne XMP strukture deklarira prostor imena, prefiks, i za svako svojstvo tip vrijednosti te kategoriju internal ili external. Kad je ta deklaracija prisutna, svojstvo postaje samoopisujuće, a klauzula 6.6.2.3.1 je zadovoljena. Bez nje validator nema izbora osim tretirati svojstvo kao neshvatljivo i odbaciti datoteku. Razlika kategorije je ovdje bitna: svojstva računa poput ovih opisuju podatke koji dolaze izvan PDF procesora, stoga se deklariraju kao external radije nego internal
Što deklaracija sheme proširenja sadrži
Ta deklaracija jest jedan rdf:Description u XMP paketu koji koristi tri AIIM-definirana prostora imena: pdfaExtension, pdfaSchema, i pdfaProperty. Unutar vreće pdfaExtension:schemas sjedi jedan unos sheme koji imenuje Factur-X shemu, daje njen pdfaSchema:namespaceURI i pdfaSchema:prefix, te potom navodi četiri svojstva unutar pdfaSchema:property sekvence. Svako od tih svojstava nosi ime, pdfaProperty:valueType vrijednosti Text, te pdfaProperty:category postavljen na external. Ilustrativni markup u nastavku pokazuje oblik takvog bloka
<rdf:Description rdf:about=""
xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/"
xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#"
xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">
<pdfaExtension:schemas>
<rdf:Bag>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>Factur-X PDFA Extension Schema</pdfaSchema:schema>
<pdfaSchema:namespaceURI>urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#</pdfaSchema:namespaceURI>
<pdfaSchema:prefix>fx</pdfaSchema:prefix>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>DocumentFileName</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>name of the embedded XML invoice file</pdfaProperty:description>
</rdf:li>
<!-- DocumentType, Version, ConformanceLevel declared the same way -->
</rdf:Seq>
</pdfaSchema:property>
</rdf:li>
</rdf:Bag>
</pdfaExtension:schemas>
</rdf:Description>
URI prostora imena i prefiks nisu fiksni stringovi. Oni prate profil. Factur-X dokument koristi urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0# uz prefiks fx, dok ZUGFeRD 2.0 datoteka odabrana kroz zugferd-invoice.xml razrješuje na sasvim drugačiji URI pod vlastitim imenom sheme. Shema proširenja mora deklarirati isti taj URI prostora imena kojeg blok svojstava zapravo koristi, inače validator i dalje ne može povezati to dvoje. PDF Library for Delphi izvodi obje te vrijednosti iz imena datoteke i verzije koju proslijedite, stoga se deklaracija i sami blok sa svojstvima uvijek slažu
Kako pomoćnik zapisuje obje polovice zajedno
Unutar PDFlibPasa ne sastavljate taj XML rukom. Stavljate dokument u PDF/A-3 mod i pozivate jednu metodu. Prva stvar za srediti jest zastavica sukladnosti, jer Factur-X zahtijeva PDF/A-3. Pozivanje SetPDFAMode(7) bira razinu PDF/A-3u, što postavlja pdfaid:part na 3 a pdfaid:conformance na U, unutar iste identifikacijske sheme. XMP paket tada nosi ispravni dio i sukladnost prije nego se doda ikakav metapodatak o računu
var
FileID: Integer;
begin
PDF.SetPDFAMode(7); // PDF/A-3u: pdfaid:part=3, conformance=U
PDF.NewDocument;
// ovdje iscrtaj stranicu računa čitljivu čovjeku
FileID := PDF.AddFacturXAssociatedFileFromString(
InvoiceXML, // raw UTF-8 XML bytes
'EN16931', // ConformanceLevel
'factur-x.xml', // naziv ugrađene datoteke
'Factur-X invoice XML', // /Desc text
'Alternative', // /AFRelationship
'1.0', // profile version
''); // neobavezni kod države
if FileID = 0 then
Exit; // not PDF/A-3, or XML/profile mismatch
PDF.SaveToFile('factur-x.pdf');
end;
Pojedinačni poziv na AddFacturXAssociatedFileFromString obavlja posao koji je toj neuspjeloj datoteci nedostajao. On ugrađuje XML kao PDF/A-3 pridruženu datoteku zajedno s odnosom kojeg ste naveli, te zabilježi ta četiri fx svojstva zajedno s imenom sheme, URI-jem prostora imena, te prefiksom za odabrani profil. Kad se dokument spremi, unutarnji korak imena ApplyFacturXMetadata ubrizgava blok sa svojstvima kao i pripadajuću deklaraciju pdfaExtension:schemas u XMP paket, pa prilagođena svojstva stignu već opisana. Metoda vraća 0 ako dokument nije u PDF/A-3 modusu ili ako se XML ne poklapa s deklariranim profilom, a to je ista brana koja zaustavlja da deformirani račun uopće dopre u datoteku već na samom početku
Slijepa točka koju provjera kontejnera ne može vidjeti
Ovo je dio kojeg treba imenovati posve jednostavno, upravo zato što je to razlog radi kojega se taj bug uspješno krije. ValidateFacturXInvoice provjerava kontejner. On potvrđuje da katalog ima /AF unos, da je imensko stablo EmbeddedFiles prisutno, da XML računa postoji, da se ime ugrađene datoteke poklapa s profilom, da guideline ID unutar samog XML-a odgovara razini sukladnosti, te da je /AFRelationship upravo onakav kakvog PDF/A-3 dozvoljava. To su stvarne provjere i one hvataju stvarne nedostatke. GetFacturXValidationIssues prijavljuje sve njih po imenu, zajedno s identifikatorima kao što su MissingCatalogAF, NotPDFA3, ConformanceGuidelineMismatch, InvalidAFRelationship, i InvalidFileNameProfile
Ono što ne provjerava jest je li XMP shema proširenja uopće prisutna te je li ispravna. Datoteka čiji je kontejner besprijekoran ali čija fx svojstva ostanu neprijavljena prolazi svaku provjeru nedostataka i vraća 1, jer ništa u toj listi ne pregledava blok pdfaExtension:schemas. To je upravo razlog zašto ručno izgrađen račun, ili onaj proizveden od strane cjevovoda koji zapiše taj blok svojstava bez deklaracije, može glatko projedriti kroz ugrađeni validator i svejedno pasti u veraPDF-u baš na klauzuli 6.6.2.3.1. Kontejnerski validator i PDF/A validator metapodataka odgovaraju na sasvim različita pitanja, i samo puni PDF/A provjerivač na koncu odgovara na to drugo pitanje
Iščitavanje problema kako biste znali koji se sloj pokvario
S obzirom da ta dva sloja padaju neovisno, prava dijagnostička navika jest prvo iščitati probleme kontejnera te čist rezultat tretirati kao izjavu isključivo o kontejneru, nikada o PDF/A metapodacima. Pokrenite ugrađenu validaciju, prikupite listu nedostataka, i djelujte po njoj prije nego posegnete za vanjskim alatom
var
Issues: WideString;
begin
if PDF.ValidateFacturXInvoice = 0 then
begin
Issues := PDF.GetFacturXValidationIssues('|');
// identifikatori na razini kontejnera, na primjer:
// MissingCatalogAF, NotPDFA3, MissingEmbeddedFilesNameTree,
// ConformanceGuidelineMismatch, InvalidAFRelationship
WriteLn('Container issues: ', Issues);
end
else
WriteLn('Container OK; verify XMP extension schema with a PDF/A checker.');
end;
Kad taj poziv vrati ime nedostatka, greška leži u kontejneru a poruka vam kaže o kojem se dijelu točno radi. Kad pak vrati čisto a veraPDF i dalje odbacuje datoteku, greška je gotovo uvijek sama XMP shema proširenja, pa rješenje jest dopustiti da AddFacturXAssociatedFileFromString zapiše te metapodatke radije nego da sami sastavljate blok sa svojstvima. Držanje tih dvaju pitanja odvojenim u vlastitom umu ono je što pretvara zbunjujuće odbacivanje u jednostavnu jednolinijsku dijagnozu: kontejnerski problemi isplivaju kroz listu nedostataka, dok problemi s deklaracijom sheme isplivavaju isključivo kroz PDF/A validator, a upravo miješanje tih dvaju jest ono što bugu omogućuje da se sakrije
Šira slika o PDF/A i PDF/UA sukladnosti, uključujući kako pokrenuti preflight prolaz prije nego datoteka napusti vaš build, pokrivena je u PDF/A i PDF/UA preflight prolasku. Ako vaš račun također mora biti pristupačan, strukturno drvo na koje se PDF/A-3a i tagged PDF oslanjaju predmet je članka o pristupačnosti tagged-PDF formata. Ovdje opisano upravljanje shemom proširenja isporučuje se kao dio PDF Library for Delphi Delphi PDF Library uz Factur-X, ZUGFeRD, kao i XRechnung profilnu podršku dokumentiranu diljem ovog bloga