Izgradili ste Factur-X račun i apsolutno svaka provjera kontejnera prolazi (passes). Katalog nosi /AF niz (array), imensko stablo (name tree) pod EmbeddedFiles razrješuje do ispravne specifikacije datoteke, ugrađeni factur-x.xml ima ispravan /AFRelationship i točni mu je iznos onaj Alternative, te taj ugrađeni (built-in) onaj ValidateFacturXInvoice također i sasvim naravno dapače vraća zapravo 1. Zatim propustite (run) istu tu datoteku kroz onaj veraPDF, onaj naoko usput to referentni provjerivač (reference checker) kakvog pak usput i rabe ti porezni portali, i on onda jednostavno eto zadanom usput pa sasvim usput onako i presudi (rules) kako čitav taj dokument uopće i posve uistinu onako nije zapravo pa dotičan validan PDF/A-3. Struktura onako pak usputno i jest posve i sasvim ispravna. Metapodaci naravno ovdje usput a onako doista to doista i zasigurno jesu naime onda naime dapače nadasve i pravi problem, a sam dotičan tu onakav doista i ovaj nadasve zadanom onaj njegov pad (failure) uistinu predstavlja zasigurno ujedno jedan doista usput od naime usput a doista dapače i naravno onih usput onakvih baš sasvim dapače a doista to i onih usput onako pa i zasigurno to onda onako onih najlakših usput na koncu nadasve sasvim eto zadanom dapače zapravo i onih za doista tu naravno posve dapače i previdjeti dapače u cijelom tom naravno naime usputno spomenutom e-invoice workflowu (radnom toku)
Taj razlog zasigurno vrijedi shvatiti u potpunosti (in full), upravo stoga jer on itekako objašnjava onu klasu nekog PDF/A nedostatka (defect) a koji nema apsolutno nikakve veze ni sa dotično onom vidljivom samom stranicom, niti pak onako doista a uistinu s tim samim onda dotičnim tamo nekim dodatkom, a s druge pak strane doista uistinu posve i nadasve sasvim eto usput on naravno uistinu dapače ima naprosto apsolutno posve baš i sve veze jedino zasigurno i naravno s tim a to točno onako kako to usput onako XMP naravno usput i zasigurno tu dapače onda to opisuje zapravo zadanom usput usput usput samog sebe. To je zapravo zamka koja se uistinu i krije (hides) iza zelene (green) provjere samog kontejnera
Ta četiri svojstva (properties) radi kojih naime taj dokument i pada
Factur-X račun zapisuje četiri prilagođena svojstva u svoj XMP paket kako bi onaj nizvodni (downstream) softver mogao jednostavno onako i pročitati profil tog računa bez da uopće rastepe (parsing) taj sami ugrađeni XML. Ona naime žive u Factur-X prostoru imena (namespace) ispod fx prefiksa: fx:DocumentFileName, fx:DocumentType, fx:Version, i fx:ConformanceLevel. Oni jesu upravo oni metapodaci koje čitač (reader) treba kako bi znao da taj PDF nosi onaj EN 16931 račun po imenu factur-x.xml na verziji 1.0
Niti jedno od tih četiri svojstva nije zapravo dio neke XMP sheme koju bi pak PDF/A unaprijed definirao (predefines). Dublin Core, XMP Basic, PDF, i one PDF/A identifikacijske sheme poznate su tom sukladnom čitaču, ali taj fx: pak doista nije. Kad onaj tamošnji veraPDF prošeće (walks) tim XMP-om te eto naiđe na to svojstvo čiji pak prostor imena ne prepoznaje (recognise), on eto krene tražiti deklaraciju koja bi mu eto i usput na koncu objasnila što to svojstvo znači. Ako takva deklaracija ovdje doista nedostaje (is absent), on odmah prijavi jedan taj usputni pad (failure) vezano uz onu ISO 19005-3 i to klauzulu 6.6.2.3.1, koja pak naravno usput zahtijeva da se svako ono nadasve usputno svojstvo i to ono doista baš koje usput dakako nije a usputno puko pak zacijelo eto izvučeno baš onako posve nadasve zacijelo iz neke naposljetku sasvim i to unaprijed nadasve zadanom usput usput i sasvim i uistinu usput nadasve dapače usput eto pak definirane onda dotično doista baš te iste naravno sheme naprosto mora usput opisati i to u jednoj PDF/A shemi proširenja (extension schema). Četiri tako neprijavljena svojstva tu predstavljaju onda i četiri ta neka zacijelo pak doista sasvim dapače i takva zapravo onako puka takozvana i ona sasvim naoko eto načina radi kojih se sasvim takva datoteka onda pak na koncu posve onda i naravno zacijelo eto nadasve doista i zasigurno tu može onda i odbaciti (rejected), a niti usput naoko jedno naime baš i samo ono doista dapače uistinu usput tu zasigurno dapače onda nije pak dapače vidljivo tek jednoj posve i doista eto puko usput doista usput eto samo uistinu naravno onoj zacijelo usput i spomenutoj usput usput takozvanoj naime onoj onakvoj tamo sasvim onakvoj nekoj tamo naravno naravno dotičnoj tu kontejnerskoj to naravno dapače naravno to naravno usputno doista dapače tu samo provjeri
Zašto taj PDF/A odbija neko usput onda posve samo usput i baš onako to golo usput dotično to neko usput samo naravno i prilagođeno svojstvo (bare custom property)
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 biti posve shvaćena i desetljećima od danas, od nekog softvera kojemu nikada nije bilo rečeno apsolutno ništa o konvencijama iz 2026. Od sukladnog (conforming) čitača se naprosto očekuje da on razluči smisao iz onog uistinu samog tog dokumenta, posve i onako bez ikakvog vanjskog registra za konzultiranje
Prilagođeni metapodaci krše to obećanje osim ako datoteka sa sobom nosi i vlastiti opis. S obzirom na golo fx:ConformanceLevel svojstvo, budući čitač ne može znati URI prostora imena uz koji se fx prefiks veže (binds to), ne može znati je li ta vrijednost neki tekst ili datum ili možda cijeli broj (integer), i ne može uopće znati opisuje li to svojstvo dotični dokument ili zapravo neki vanjski resurs. Mehanizam onih PDF/A shema proširenja (extension schema) uistinu zatvara tu prazninu. On datoteci omogućuje da deklarira, unutar fiksne XMP strukture, sami prostor imena, prefiks, i tip vrijednosti kao i kategoriju (internal ili pak external) svakog svog svojstva. Jednom kad je deklaracija prisutna to svojstvo postaje samodeskrptivno, a klauzula 6.6.2.3.1 se zadovoljava. Bez nje, validator nema izbora osim postupati (treat) s tim svojstvom kao sa nečim neshvatljivim (unintelligible) i srušiti tu datoteku. Razlikovna kategorija je bitna ovdje: svojstva nekog računa opisuju podatke koji dolaze izvan PDF procesora, stoga ih se deklarira kao external radije no internal
Što deklaracija sheme proširenja sadrži
Ta deklaracija jest jedan rdf:Description u XMP paketu koji koristi ona tri AIIM-definirana prostora imena (namespaces) i to pdfaExtension, pdfaSchema, i pdfaProperty. Unutar jedne pdfaExtension:schemas vreće (bag) sjedi tako jedan unos sheme koji imenuje (names) tu Factur-X shemu, daje njen pdfaSchema:namespaceURI i pdfaSchema:prefix, te potom navodi i ona četiri svojstva unutar pdfaSchema:property sekvence. Svako od tih svojstava nosi ime, taj pdfaProperty:valueType onog Text, te pdfaProperty:category postavljen na external. Taj dolje ilustrativni markup pokazuje naravno upravo 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>
Taj URI prostora imena i taj prefiks nisu fiksni stringovi. Oni prate (follow) profil. Factur-X dokument koristi urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0# uz fx prefiks, dok ZUGFeRD 2.0 datoteka i to odabrana kroz zugferd-invoice.xml razrješuje na jedan sasvim drugačiji URI pod njenim vlastitim imenom sheme. Shema proširenja onda mora deklarirati isti taj URI prostora imena kojega taj blok svojstava zapravo i koristi, inače validator i dalje ne može spojiti to oboje (connect the two). PDFlibPas pak izvodi (derives) obje te vrijednosti iz onog imena datoteke te verzije koju proslijedite (pass), stoga se onda deklaracija kao i taj sami blok sa svojstvima naprosto eto zauvijek zapravo slažu (agree)
Kako pomoćnik zapisuje obje te polovice skupa
Unutar PDFlibPasa ne sastavljate vi taj XML rukom. Vi stavljate dokument u PDF/A-3 mod (mode) i pozivate jednu metodu. Prva stvar za srediti (settle) jest ona zastavica sukladnosti, jer Factur-X naprosto zahtijeva PDF/A-3. Pozivanje SetPDFAMode(7) onda i bira PDF/A-3u razinu, što pak onda postavlja pdfaid:part u 3 a pdfaid:conformance u U, i to sve baš unutar te same identifikacijske sheme. Taj XMP paket onda posve sa sobom na koncu donosi ispravni dio i tu sukladnost prije nego se uopće eto ikakav naime eto tu metapodatak o računu dapače usput i doda
var
FileID: Integer;
begin
PDF.SetPDFAMode(7); // PDF/A-3u: pdfaid:part=3, conformance=U
PDF.NewDocument;
// draw the human-readable invoice page here
FileID := PDF.AddFacturXAssociatedFileFromString(
InvoiceXML, // raw UTF-8 XML bytes
'EN16931', // ConformanceLevel
'factur-x.xml', // embedded file name
'Factur-X invoice XML', // /Desc text
'Alternative', // /AFRelationship
'1.0', // profile version
''); // optional country code
if FileID = 0 then
Exit; // not PDF/A-3, or XML/profile mismatch
PDF.SaveToFile('factur-x.pdf');
end;
Pojedinačni (single) poziv na AddFacturXAssociatedFileFromString odrađuje posao koji je toj datoteci koja je padala nedostajao (was missing). On ugrađuje XML kao jednu PDF/A-3 pridruženu datoteku skupa s odnosom (relationship) kojeg ste naveli, te zabilježi ta četiri fx svojstva zajedno s imenom sheme, URI-jem prostora imena, te s prefiksom za odabrani profil. Kad se taj dokument spremi, jedan unutarnji korak pod imenom ApplyFacturXMetadata ubrizgava (injects) onaj blok sa svojstvima kao i pripadajuću pdfaExtension:schemas deklaraciju u onaj XMP paket, pa ta prilagođena svojstva stignu već naprosto opisana. Metoda vraća 0 ako sam dokument nije u PDF/A-3 modusu (mode) ili ako se sami taj XML ne poklapa s deklariranim profilom, a baš to jest i ta ista brana (guard) koja zaustavlja da jedan deformirani (malformed) račun uopće dopre u datoteku već onako u samom startu (in the first place)
Slijepa točka (blind spot) koju provjera kontejnera ne može vidjeti
Ovo je baš onaj dio kojega naprosto treba imenovati (name) potpuno i posve jednostavno (plainly), upravo zato što je to onaj razlog radi kojega se taj bug doista uspješno i krije. Taj ValidateFacturXInvoice provjerava onaj kontejner. On potvrđuje da katalog ima onaj /AF unos, da je EmbeddedFiles imensko stablo (name tree) tu prisutno, da onaj XML računa postoji, da se ime ugrađene datoteke poklapa s profilom, da tamošnji guideline ID unutar samog XML-a dapače i sasvim odgovara uz razinu sukladnosti, te uistinu i da onaj /AFRelationship jest upravo onakav kakvog sam taj PDF/A-3 onako usput i dozvoljava. To jesu one stvarne provjere (real checks) te one i hvataju te nadasve sasvim stvarne nedostatke (defects). Taj GetFacturXValidationIssues prijavljuje sve njih eto posve i to upravo i samo po imenu (by name), zajedno uz identifikatore kao što jesu MissingCatalogAF, NotPDFA3, ConformanceGuidelineMismatch, InvalidAFRelationship, i onaj usputni InvalidFileNameProfile
Ono pak što on nikako usput ne provjerava jest upravo i da li je naravno ta XMP shema proširenja uopće tu prisutna te je li eto ispravna. Datoteka čiji je kontejner besprijekoran (flawless) ali čija ta fx svojstva onako ostanu neprijavljena jednostavno prolazi ama baš svaku provjeru nedostataka i dapače vraća onaj 1, upravo jer apsolutno ništa u toj istoj listi ne pregledava onaj dotični pdfaExtension:schemas blok. To eto točno i jest dapače doista i razlog zašto neki onakav ručno tu i usput doista usput nadasve eto zacijelo izgrađen onakav račun, ili pak dapače onaj koji doista uistinu sasvim dapače jest onda eto usput i naravno proizveden od strane nekog usputnog cjevovoda (pipeline) dapače koji usput onako i zapiše dotični taj usput onakav dapače i usput onakav pak dotični onaj blok svojstava na kraju bez te deklaracije, može onako eto naravno usput naravno onako i i sasvim uistinu dapače onako posve onako eto glatko eto i projedriti (sail) skroz i onako dapače kroz onaj tu usput ugrađeni validator i eto dapače onako još eto i svejedno dapače eto pasti u onom tamo veraPDF baš i na samoj klauzuli 6.6.2.3.1. Kontejnerski validator te usput i dotično onaj PDF/A validator metapodataka odgovaraju naravno na sasvim različita pitanja, i onda dapače eto zacijelo tu doista i sasvim točno onako to i samo taj doista uistinu i zadanom i doista taj puni PDF/A provjerivač na koncu samo i odgovara na onako usput ono onda i to zacijelo dapače tu drugo naravno onda pitanje
Iščitavanje problema (issues) kako biste znali koji se sloj pokvario (broke)
S obzirom da ta dva sloja padaju (fail) neovisno, onda doista i ona prava dijagnostička navika tu jest doista da prvo iščitate probleme onog kontejnera te jedan taj čisti rezultat naprosto usput onako tretirate doista kao izjavu isključivo i samo o tom kontejneru, nikada pak o onim tamošnjim PDF/A metapodacima. Propustite (run) tu ugrađenu validaciju, prikupite onu listu nedostataka (issues), i djelujte po njoj prije nego li usput na koncu i uopće posegnete za kakvim vanjskim onako alatom
var
Issues: WideString;
begin
if PDF.ValidateFacturXInvoice = 0 then
begin
Issues := PDF.GetFacturXValidationIssues('|');
// 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 (issue name), greška leži u kontejneru a poruka vam kaže o kojem se dijelu točno radi. Kad pak vrati čisto (clean) a veraPDF i dalje odbacuje tu datoteku, onda je greška gotovo uvijek sama XMP shema proširenja, pa rješenje ovdje jest dopustiti da AddFacturXAssociatedFileFromString zapiše te metapodatke radije no da sami sastavljate (constructing) onaj blok sa svojstvima. Držanje tih dvaju pitanja sasvim odvojenim eto u vlastitom umu jest pak ono što pretvara kakvo zbunjujuće odbacivanje u jednostavnu jednolinijsku dapače dijagnozu: oni kontejnerski problemi isplivaju kroz listu nedostataka, dok pak oni s deklaracijom sheme usputno isplivavaju (surface) isključivo kroz sami PDF/A validator, a eto upravo naprosto to miješanje (confusing) ta dva jest upravo ono što onda omogućuje onom bugu da se onako naprosto uistinu usput i skrije (hide)
Šira slika (picture) o PDF/A i PDF/UA sukladnosti, uključujući tu i to kako pokrenuti taj takozvani preflight prolaz (pass) prije nego datoteka uopće i napusti vaš sami build, doista je pak onako usputno tu pokrivena u PDF/A te PDF/UA onom preflight takozvanom prolasku (walkthrough). Ako vaš račun također mora dapače biti i pristupačan (accessible), baš ono strukturno drvo na koje se PDF/A-3a te i sami taj dotični onako tagged PDF onda i oslanjaju (depend on) uistinu jest onako i predmetom onog usputnog članka o pristupačnosti samog tagged-PDF formata. Ono ovdje tu onako i usputno doista dapače opisano upravljanje nad shemom proširenja (extension schema) uistinu se usput i isporučuje (ships) eto kao sami dio unutar one nadasve doista i baš eto usput PDFlibPas Delphi PDF Library i to naravno onako naprosto zacijelo eto uz Factur-X, ZUGFeRD, kao i onu XRechnung pak onako posve i dapače tu onako profilnu podršku naravno eto sasvim usput dokumentiranu dapače tu i eto diljem i uistinu po cijelom ovom ovdje blogu