Ön felépített egy Factur-X számlát, és minden konténerellenőrzés (container check) átmegy. A katalógus (catalog) hordoz egy /AF tömböt, az EmbeddedFiles névfa (name tree) a megfelelő fájlspecifikációra (file specification) oldódik fel, a beágyazott factur-x.xml rendelkezik a megfelelő /AFRelationship Alternative értékkel, és a beépített ValidateFacturXInvoice 1-et ad vissza. Ezután átfuttatja ugyanezt a fájlt a veraPDF-en, az adóportálok (tax portals) által használt referenciaellenőrzőn, és az úgy ítél (rules), hogy a teljes dokumentum nem egy érvényes PDF/A-3. A struktúra megfelelő. A metaadat (metadata) a probléma, és a hibát az egyik legkönnyebb figyelmen kívül hagyni az egész e-számla munkafolyamatban
Az okot érdemes teljes egészében megérteni, mert megmagyarázza a PDF/A hibáknak (defect) egy olyan osztályát, amelynek semmi köze a látható oldalhoz vagy a melléklethez, viszont minden köze van ahhoz, hogy az XMP hogyan írja le önmagát. Ez az a csapda (trap), amely egy zöld konténerellenőrzés mögött bújik meg
A négy tulajdonság, amely megbuktatja a fájlt
Egy Factur-X számla négy egyedi tulajdonságot (custom properties) ír az XMP csomagjába (packet), így a feldolgozási láncban lévő (downstream) szoftverek el tudják olvasni a számlaprofilt anélkül, hogy értelmezniük (parsing) kellene a beágyazott XML-t. Ezek a Factur-X névtérben (namespace) élnek az fx előtag (prefix) alatt: fx:DocumentFileName, fx:DocumentType, fx:Version és fx:ConformanceLevel. Ezek pontosan azok a metaadatok, amelyekre egy olvasónak (reader) szüksége van ahhoz, hogy tudja: ez a PDF egy EN 16931 szabványú, factur-x.xml nevű, 1.0-s verziójú számlát hordoz
Ezen négy tulajdonság egyike sem része olyan XMP sémának (schema), amelyet a PDF/A előre definiál. A Dublin Core, az XMP Basic, a PDF és a PDF/A azonosítási (identification) sémák ismertek egy konform olvasó (conforming reader) számára, de az fx: nem. Amikor a veraPDF végigmegy az XMP-n, és elér egy olyan tulajdonsághoz, amelynek a névterét nem ismeri fel, egy olyan deklarációt (declaration) keres, amely megmondaná neki, mit jelent a tulajdonság. Ha ez a deklaráció hiányzik, hibát jelent az ISO 19005-3 szabvány 6.6.2.3.1-es pontja megsértésére hivatkozva, amely megköveteli, hogy minden olyan tulajdonságot, amely nem egy előre definiált sémából származik, egy PDF/A kiterjesztési sémában (extension schema) kell leírni. Négy nem deklarált tulajdonság, négy módja annak, hogy a fájlt elutasítsák, és ezek egyike sem látható egy konténerellenőrzés számára
Miért utasítja el a PDF/A a csupasz (bare) egyedi tulajdonságot
A szabály pedánsnak tűnhet, amíg nem emlékszik, mire való a PDF/A. A formátum azért létezik, hogy egy fájlt évtizedek múlva is meg lehessen nyitni és meg lehessen érteni egy olyan szoftverrel, amelynek soha nem mondtak semmit a 2026-os konvenciókról. Egy konform olvasótól (conforming reader) elvárják, hogy csak a dokumentumból értse meg a dokumentumot, mindenféle külső regiszter (registry) konzultációja nélkül
Az egyedi metaadatok (custom metadata) megszegik ezt az ígéretet, kivéve, ha a fájl hordozza a saját leírását. Egy csupasz fx:ConformanceLevel tulajdonság esetén egy jövőbeli olvasó nem tudhatja, hogy az fx előtag milyen névtér (namespace) URI-hez kötődik, hogy az érték szöveg, dátum vagy egész szám-e, vagy hogy a tulajdonság magát a dokumentumot vagy valamilyen külső erőforrást ír-e le. A PDF/A kiterjesztési séma (extension schema) mechanizmusa bezárja ezt a rést. Lehetővé teszi a fájl számára, hogy egy rögzített XMP struktúrában deklarálja a névteret, az előtagot (prefix), valamint minden tulajdonsághoz egy értéktípust (value type) és az internal vagy external kategóriát. Ha ez a deklaráció jelen van, a tulajdonság önleíróvá (self-describing) válik, és a 6.6.2.3.1 záradék teljesül. Enélkül a validátornak (validator) nincs más választása, mint a tulajdonságot értelmezhetetlenként kezelni és megbuktatni a fájlt. A kategória (category) megkülönböztetése itt számít: az ilyen számlatulajdonságok olyan adatokat írnak le, amelyek a PDF-feldolgozón (PDF processor) kívülről származnak, ezért external-ként (külső) vannak deklarálva, nem pedig internal-ként (belső)
Mit tartalmaz a kiterjesztési séma (extension schema) deklarációja
A deklaráció egy rdf:Description az XMP csomagban, amely a három AIIM által definiált névteret (pdfaExtension, pdfaSchema és pdfaProperty) használja. Egy pdfaExtension:schemas bag-en belül (inside a bag) ül egy sémabejegyzés, amely megnevezi a Factur-X sémát, megadja annak pdfaSchema:namespaceURI és pdfaSchema:prefix értékét, majd felsorolja a négy tulajdonságot egy pdfaSchema:property szekvenciában. Minden tulajdonság (property) hordoz egy nevet, egy Text értékű pdfaProperty:valueType-ot és egy external értékű pdfaProperty:category-t. Az alábbi illusztratív jelölés (markup) megmutatja ennek a blokknak az alakját
<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>
A névtér (namespace) URI és az előtag (prefix) nem rögzített karakterláncok. Ezek követik a profilt. Egy Factur-X dokumentum a urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0# értéket használja az fx előtaggal, míg egy zugferd-invoice.xml-en keresztül kiválasztott ZUGFeRD 2.0 fájl egy másik URI-ra oldódik fel (resolves) a saját sémaneve (schema name) alatt. A kiterjesztési sémának ugyanazt a névtér URI-t kell deklarálnia, amelyet a tulajdonságblokk (property block) ténylegesen használ, különben a validátor (validator) továbbra sem tudja összekapcsolni a kettőt. A PDFlibPas mindkét értéket az Ön által átadott fájlnévből és verzióból származtatja (derives), így a deklaráció és a tulajdonságblokk mindig megegyezik
Hogyan írja meg a segéd (helper) mindkét felet együtt
A PDFlibPas-ban ezt az XML-t nem kézzel állítja össze (assemble by hand). Beteszi a dokumentumot PDF/A-3 módba (mode), és meghív egy metódust. Az első dolog, amit el kell intézni, a megfelelőségi jelző (conformance flag), mert a Factur-X megköveteli a PDF/A-3-at. A SetPDFAMode(7) hívása kiválasztja a PDF/A-3u szintet, amely beállítja a pdfaid:part-ot 3-ra és a pdfaid:conformance-ot U-ra az azonosítási sémában. Az XMP csomag (packet) most már a megfelelő part és conformance értékeket hordozza, mielőtt bármilyen számlametaadat hozzáadásra kerülne
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;
Az AddFacturXAssociatedFileFromString egyetlen hívása elvégzi azt a munkát, amely a hibás (failing) fájlból hiányzott. Beágyazza az XML-t PDF/A-3 társított fájlként (associated file) a megnevezett kapcsolattal (relationship), és rögzíti a négy fx tulajdonságot (properties), a sémanévvel, a névtér (namespace) URI-val és a kiválasztott profilhoz tartozó előtaggal (prefix) együtt. A dokumentum mentésekor (is saved) egy ApplyFacturXMetadata nevű belső lépés befecskendezi (injects) mind a tulajdonságblokkot (property block), mind a hozzá tartozó pdfaExtension:schemas deklarációt az XMP csomagba (packet), így az egyedi tulajdonságok (custom properties) már leírva érkeznek meg. A metódus 0-t ad vissza, ha a dokumentum nincs PDF/A-3 módban, vagy ha az XML nem egyezik a deklarált profillal; ez ugyanaz az őr (guard), amely megakadályozza, hogy egy hibás (malformed) számla egyáltalán bekerüljön a fájlba
A vakfolt (blind spot), amelyet a konténerellenőrzés nem lát
Ezt a részt világosan meg kell nevezni (name plainly), mert ez az oka a hiba (bug) megbújásának. A ValidateFacturXInvoice a konténert (container) ellenőrzi. Megerősíti, hogy a katalógusnak van /AF bejegyzése, jelen van az EmbeddedFiles névfa (name tree), létezik a számla XML, a beágyazott fájl neve megegyezik a profillal, az XML-ben lévő irányelvi (guideline) azonosító megegyezik a megfelelőségi szinttel, és az /AFRelationship olyan, amit a PDF/A-3 megenged. Ezek valódi ellenőrzések, és valódi hibákat (defects) csípnek el. A GetFacturXValidationIssues név szerint jelenti őket olyan azonosítókkal, mint a MissingCatalogAF, NotPDFA3, ConformanceGuidelineMismatch, InvalidAFRelationship és InvalidFileNameProfile
Amit nem ellenőriz, az az, hogy az XMP kiterjesztési séma (extension schema) jelen van-e és helyes-e. Egy olyan fájl, amelynek konténere hibátlan (flawless), de az fx tulajdonságai nincsenek deklarálva (undeclared), minden problémaellenőrzésen (issue check) átmegy és 1-et ad vissza, mivel a listában semmi sem vizsgálja a pdfaExtension:schemas blokkot. Pontosan ez az oka annak, hogy egy kézzel (hand-built) összeállított számla, vagy egy olyan, amelyet egy folyamat (pipeline) állított elő, amely a tulajdonságblokkot a deklaráció nélkül írta meg, simán átcsusszanhat (sail through) a beépített validátoron, és a 6.6.2.3.1. záradék alapján mégis megbukik a veraPDF-en. A konténervalidátor (container validator) és a PDF/A metaadat-validátor más-más kérdésekre válaszol, és csak a teljes PDF/A ellenőrző (checker) válaszolja meg a másodikat
A problémák (issues) olvasása, hogy tudja, melyik réteg tört el
Mivel a két réteg egymástól függetlenül bukik meg (fail independently), a helyes diagnosztikai (diagnostic) szokás az, hogy először a konténerproblémákat (container issues) olvassa el, és egy tiszta eredményt csak a konténerre vonatkozó állításként kezel, a PDF/A metaadatokra soha. Futtassa le a beépített validálást (built-in validation), gyűjtse össze a hibalistát (issue list), és cselekedjen (act on it) az alapján, mielőtt külső eszközhöz nyúlna
var
Issues: WideString;
begin
if PDF.ValidateFacturXInvoice = 0 then
begin
Issues := PDF.GetFacturXValidationIssues('|');
// container-level identifiers, for example:
// MissingCatalogAF, NotPDFA3, MissingEmbeddedFilesNameTree,
// ConformanceGuidelineMismatch, InvalidAFRelationship
WriteLn('Container issues: ', Issues);
end
else
WriteLn('Container OK; verify XMP extension schema with a PDF/A checker.');
end;
Amikor ez a hívás egy probléma nevet (issue name) ad vissza, a hiba a konténerben (container) van, és az üzenet megmondja, melyik részben. Ha tiszta (clean) eredményt ad vissza, és a veraPDF mégis elutasítja a fájlt, a hiba (fault) szinte mindig az XMP kiterjesztési séma (extension schema), a javítás pedig az, hogy engedi, hogy az AddFacturXAssociatedFileFromString írja a metaadatokat (metadata), ahelyett, hogy saját maga építené fel a tulajdonságblokkot (property block). A két kérdés elkülönítve tartása a saját fejében az, ami egy rejtélyes (baffling) elutasítást egysoros diagnózissá (diagnosis) változtat: a konténerproblémák (container problems) a hibalistán (issue list) keresztül kerülnek a felszínre, a sémadeklarációs (schema-declaration) problémák csak egy PDF/A validátoron keresztül kerülnek a felszínre, és a kettő összekeverése az, ami engedi a hibát elrejtőzni
A tágabb PDF/A és PDF/UA megfelelőségi (conformance) képet, beleértve azt, hogy hogyan futtasson le egy preflight lépést (pass), mielőtt egy fájl elhagyja a buildet, a PDF/A és a PDF/UA preflight bemutatásában ismertetjük. Ha a számlájának is akadálymentesítettnek (accessible) kell lennie, a PDF/A-3a és a címkézett (tagged) PDF alapjául szolgáló struktúrafa (structure tree) a címkézett PDF akadálymentesítési cikk témája. Az itt leírt kiterjesztési séma (extension schema) kezelés a PDFlibPas Delphi PDF Library részeként érkezik (ships) az ezen a blogon dokumentált Factur-X, ZUGFeRD és XRechnung profiltámogatás (profile support) mellett