PDFlibPas validerer PDF/UA-2-filer (ISO 14289-2) i Delphi via TPDFlib.CheckFilePDFUACompliance med target part sat til 2, hvilket kører en separat PDF/UA-2-profil: den opløser strukturreller gennem PDF 2.0-navnerum og /RoleMapNS, rapporterer afkortet eller ulæseligt input som en fejl, og returnerer en dækningsrapport, der aldrig hævder fuld certificering
Det sidste punkt betyder mere, end det lyder. Tilgængelighedsvalidering er et felt, hvor et grønt flueben kopieres ind i en indkøbstabel og aldrig sættes spørgsmålstegn ved igen. En validator, der i stilhed springer halvdelen af standarden over og stadig udskriver "pass", er værre end ingen validator, fordi den omdanner et ukendt til en falsk kendt. PDFlibPas tager den modsatte indstilling: tjek det, der kan tjekkes maskinelt, sig højt, hvad der ikke blev tjekket, og behandle ethvert "kunne ikke gennemføres" som et fund frem for en succes
Hvorfor kan man ikke validere PDF/UA-2 med PDF/UA-1-regler?
PDF/UA-2 er ikke PDF/UA-1 med et højere delnummer. PDF/UA-1 bygger på PDF 1.7 og ét enkelt fladt role map; PDF/UA-2 bygger på PDF 2.0 (ISO 32000-2), hvor hvert strukturelement kan tilhøre et navnerum, og hvert navnerum har sit eget role map. En UA-1-tjekker rettet mod en UA-2-fil vil både overse reelle problemer og finde på falske
De falske er den pinlige del. PDF/UA-1-validatorer håndhæver typisk regler om Note-elementer med et ID og om hvordan den unummererede H-overskrift må bruges. Ingen af reglerne kan overføres. I PDF 2.0-ens struktur-navnerum udtrykkes fodnoter med FENote, og overskrifter er H1 til Hn uden seks-niveaus-loft. PDF/UA-2 går videre og forbyder den unummererede H-rolle helt ud. Anvender man UA-1-overskriftslogik på det træ, klager man enten over ting, standarden tillader, eller lader det ene, den forbyder, glide igennem
Derfor er PDFlibPas' PDF/UA-2-profil en separat kodevej, ikke et flag på den gamle. Den nægter også at genbruge UA-1-klausulnumre. Diagnostik, der deles med UA-1-tjekkeren, genknyttes til ISO 14289-2 i UA-2-rapporter, og hvor et klausulnummer ikke er blevet verificeret mod standardteksten, efterlader rapporten klausulfeltet tomt frem for at gætte. En tom klausul er mindre tilfredsstillende end et selvsikkert klausulnummer, men det er det eneste forsvarlige output, når ingen har bekræftet mappingen
Hvordan PDFlibPas opløser roller gennem RoleMapNS
PDFlibPas opløser hver strukturerolle til en standardrolle i et kendt navnerum, følger /RoleMapNS-kæder på tværs af navnerum og rapporterer enhver kæde, der ender på en brugerdefineret rolle, looper eller bryder mapping-reglerne. Dette er kernen i PDF/UA-2-strukturvalidering, fordi hjælpemiddelteknologi kun forstår standardroller; en brugerdefineret /InvoiceLine betyder ingenting, før den lander på noget som P eller TR
Opløseren starter fra elementets /S-navn og dets /NS-navnerum. Uden navnerum ligger elementet implicit i PDF 1.7-standardnavnerummet, og det ældre /RoleMap i strukturtræ-roden gælder. Med et navnerum gælder navnerums-dictionaryens eget /RoleMapNS, og en mapping kan pege på en rolle i et andet navnerum via et to-elementers-array. Tjekkene, der falder ud af dette, er konkrete:
- Et navnerum, der refereres fra et strukturelement, skal være en indirekte dictionary med en gyldig
/NS-URI og skal være opført i strukturtræ-rodens/Namespaces-array (diagnostik 10054) - En brugerdefineret rolle skal til sidst opløses til en standardrolle i PDF 1.7-navnerummet, PDF 2.0-navnerummet (
http://iso.org/pdf2/ssn) eller MathML-navnerummet; cirkulære kæder og blindgyder rapporteres som 10055 - En standardrolle må ikke remappes til en brugerdefineret, og en rolle må ikke remappes inden for sit eget eksplicitte navnerum
- Strukturoden skal indeholde præcis ét
Document-element i PDF 2.0-navnerummet (10057), og hvert elements/Pskal pege på sin faktiske forælder (10058) - En unummereret
Heller et ældre PDF 1.7-Note, der ikke er mappet til en PDF 2.0-rolle, rapporteres som 10056
Én detalje er værd at kopiere ind i eget tooling: PDFlibPas validerer hver erklæret mapping, ikke kun dem, der kan nås fra træet. En ødelagt post i et role map, som intet element pt. bruger, er stadig en latent defekt, for den næste indholdsopdatering begynder at bruge den. MathML håndteres også ærligt. MathML-navnerummet anerkendes som et gyldigt opløsningsmål, men MathML-vokabularet selv valideres ikke, og dækningsrapporten siger det udtrykkeligt
Sådan kører man et PDF/UA-2-tjek fra Delphi
TPDFlib.CheckFilePDFUACompliance er ét-kalds-indgangspunktet: giv filen, adgangskoden, target part og options, og man får et string list-handle tilbage med kodede problemer. Et handle på nul med LastErrorCode lig nul betyder, at de implementerede tjek fandt ingenting; en LastErrorCode forskellig fra nul betyder, at kaldet selv fejlede
var
Lib: TPDFlib;
Issues, I: Integer;
begin
Lib := TPDFlib.Create;
try
// TargetPart: 0 = findes ud fra XMP pdfuaid:part, 1 = PDF/UA-1, 2 = PDF/UA-2
// Options: 1 = stop ved den første fejl, 0 = saml alle problemer
Issues := Lib.CheckFilePDFUACompliance('report.pdf', '', 2, 0);
if Issues = 0 then
begin
if Lib.LastErrorCode <> 0 then
Writeln('Validation did not run, error ', Lib.LastErrorCode)
else
Writeln('No issues from the implemented PDF/UA-2 checks');
end
else
try
for I := 1 to Lib.GetStringListCount(Issues) do // elementerne er 1-baserede
Writeln(Lib.GetStringListItem(Issues, I));
finally
Lib.ReleaseStringList(Issues);
end;
finally
Lib.Free;
end;
end;
Vælg target part med omtanke. Et target på 0 læser pdfuaid:part fra XMP-metadataerne og vælger profilen ud fra det, hvilket passer til en generisk indbakke-validator. Til egen output-pipeline giver man 2 eksplicit. Har ens generator glemt at skrive identifikationen, falder auto-detektering tilbage til UA-1-reglerne, og man validerer den forkerte standard; en eksplicit 2 giver i stedet diagnostik 10050 for den manglende del, plus 10051, hvis pdfuaid:rev ikke er 2024, og 10052, hvis den effektive PDF-version ikke er 2.0. På authoring-siden skriver TPDFlib.SetPDFUA2Mode den identifikation, hæver versionen til 2.0 og vælger PDF 2.0-strukturnavnerummet som standard; navnerumsmodellen selv gennemgås i gennemgangen af PDF 2.0-, PDF/A-4- og PDF/UA-2-navnerum
Hvad sker der, når validatoren løber tør for budget?
PDFlibPas fejler lukket: når PDF/UA-2-tjekkeren rammer en traverseringsgrænse, en cyklus, en parsergrænse eller et dokument, den ikke kan åbne, udsender den en diagnostik, og et resultat uden diagnostik bliver aldrig forfremmet til et pass. Diagnostik 10059 er reserveret til netop dette "læseren kunne ikke gennemføre"-tilfælde
Budgetterne er eksplicitte og offentliggjort i coverage-JSON'en: strukturdybde 256, 100.000 struktur-objekter og 256 hop langs enhver role map-kæde. Tallene findes, fordi strukturtræer kommer fra utroværdigt input. En fjendtlig eller blot ødelagt fil kan indlejre elementer tusindvis af niveauer dybt, få et barn til at pege tilbage på en forfader eller bygge et role map, der kæder gennem hundredvis af navnerum. En validator uden budgetter crasher enten eller hænger, og en validator med budgetter men uden diagnostik gør noget subtilere og værre: den stopper tidligt, finder intet galt i den del, den læste, og rapporterer succes
Samme princip gælder ét niveau oppe. Returnerer den underliggende læser en score under 100 uden problemlinjer, hvilket kan ske, når parsingen afbrydes, før nogen regel kører, indsætter PDFlibPas en 10059-linje, så den tomme liste ikke kan forveksles med et rent resultat. En exception under tjekket bliver også til en 10059-linje. Det er en lille mængde kode, og den lukker den mest almindelige måde, hvorpå valideringspipelines lyver for deres ejere
Del én parsing med PDF/A og byg en rapport
Til batch-arbejde parser validation pipeline-API'et en fil én gang og kører flere tjek mod den delte parsing. RunPDFUAValidationPipelineTask er PDF/UA-medlemmet af den familie og tager de samme target part-værdier som ét-kalds-funktionen, hvilket sparer en PDF/A plus PDF/UA-2-preflight for to fulde læsninger af et stort dokument
var
Pipe, PDFAIssues, UAIssues: Integer;
Json: WideString;
begin
Pipe := Lib.BeginValidationPipeline('archive.pdf', '');
if Pipe = 0 then
Exit;
try
PDFAIssues := Lib.RunValidationPipelineTask(Pipe, 1, 0); // 1 = PDF/A
UAIssues := Lib.RunPDFUAValidationPipelineTask(Pipe, 2, 0); // PDF/UA-2
// ... inspicer og frigiv begge handles som i forrige eksempel ...
Writeln('Parses: ', Lib.GetValidationPipelineParseCount(Pipe));
// ComplianceTests: 1 = PDF/A, 2 = PDF/UA, 0 = begge; ReportFormat 1 = JSON
Json := Lib.CreateValidationPipelineReport(Pipe, 0, 0, 1);
finally
Lib.ReleaseValidationPipeline(Pipe);
end;
end;
Den strukturerede rapport mærker tilgængelighedssektionen PDF/UA-2 og ISO 14289-2, når filen identificerer sig som part 2, og hver PDF/UA-sektion bærer "fullCertification": false sammen med det indlejrede coverage-objekt. Tekst-preflight-rapporten tilføjer en linje, der oplyser, at kun implementerede tjek kørte, og at fuld tilgængelighedscertificering kræver yderligere validering og menneskelig gennemgang. De bredere rapportformater, rule IDs og CI-gating-mønstre er beskrevet i PDF/A- og PDF/UA-preflight-guiden
Hvad garanterer dækningsrapporten rent faktisk?
TPDFlib.GetPDFUAReadValidationCoverageJSON garanterer én ting: en præcis liste over, hvad PDF/UA-2-tjekkeren undersøgte, og hvad den ikke gjorde. For part 2 returnerer den fullCertification fastlåst til false, et checked-array, et unverified-array og traverseringsgrænserne. Den garanterer ikke, at en fil er tilgængelig, og den er designet, så ingen kodevej kan få den til at sige andet
var
Coverage: WideString;
begin
Coverage := Lib.GetPDFUAReadValidationCoverageJSON(2);
// Gem den ved siden af valideringsresultatet, ikke i stedet for det
TFile.WriteAllText('report.coverage.json', Coverage, TEncoding.UTF8);
if Pos('"fullCertification":false', Coverage) > 0 then
Writeln('Machine checks only; schedule a human accessibility review');
end;
Checked-listen dækker identifikation (part, revision, prefix), effektiv PDF-version, titelmetadata, /MarkInfo, DisplayDocTitle, navnerumsreferencer, role map-opløsning, dokumentroden, struktur-forældre, træcykler og H- og Note-reglerne. Unverified-listen er lige så specifik: content tagging og læserækkefølge, struktur-indeslutning, fonte og Unicode-mapping, annotationer og formularer, naturligt sprog, alternative beskrivelser, MathML-vokabularet og menneskelig tilgængelighedsgennemgang. Flere af dem er ikke engang mekanisk afgørelige. Ingen parser kan fortælle, om en alt-tekst rent faktisk beskriver diagrammet, eller om læserækkefølgen giver mening for en, der lytter til den
Behandl coverage-JSON'en som en del af resultatet. Arkivér den ved hver valideringskørsel, og når en auditor spørger, hvad "pass" betød på en given dato, kan man udlevere det præcise scope i stedet for at rekonstruere det ud fra hukommelsen og et versionsnummer
Krydstjek mod veraPDF
PDF/UA-2-kernen blev krydstjekket mod veraPDF 1.30.3 command-line-validator med dens ua2-profil, og resultaterne stemmer, hvor dækningen overlapper. Et uafhængigt genereret gyldigt core-sample bestod begge værktøjer; et sample, der erklærede pdfuaid:rev 2023, og et sample, der brugte den unummererede H-rolle, fejlede i begge
Et fjerde sample er det, der er værd at tale om. Det indeholdt drawing-indhold, der slet ikke var tagget, og veraPDF flaggede det, mens PDFlibPas' core-tjek ikke gjorde, fordi content tagging ligger uden for den nuværende dækning. Det hul er præcis derfor, content-tagging-and-reading-order står øverst på unverified-listen. At køre en anden validator er billig forsikring, og uenighed mellem to værktøjer er ofte den hurtigste måde at finde grænsen for, hvad hver enkelt tjekker. Til authoring-siden af samme problem, at bygge træer, der består fra starten, se guiden til tagged PDF-strukturtræer
FAQ
Certificerer PDFlibPas en fil som PDF/UA-2-kompatibel?
Nej. PDFlibPas kører de implementerede maskine-tjek for PDF/UA-2 og returnerer en dækningsrapport med fullCertification altid false og lister alle områder, der stadig kræver andre værktøjer eller menneskelig gennemgang
Hvilken TargetPart-værdi skal man give til CheckFilePDFUACompliance?
Giv 2, når man ved, at filen skal være PDF/UA-2, så manglende identifikation rapporteres. Giv 0 for automatisk at finde delen ud fra XMP pdfuaid:part og 1 for at gennemtvinge PDF/UA-1-reglerne
Hvad betyder diagnostik 10059 i en PDF/UA-2-rapport?
Diagnostik 10059 betyder, at validatoren ikke kunne gennemføre: filen kunne ikke parses eller åbnes, en traverseringsgrænse blev overskredet, en cyklus blev fundet, eller der opstod en exception. Den tæller altid som en fejl, aldrig som et pass
PDF/UA-2-validering, den delte validation pipeline og PDF 2.0-authoring-API'erne følger med i losLab PDF Library for Delphi sammen med PDF/A-preflight og strukturerede valideringsrapporter