Teknik Makale

Delphi'de PDF/UA-2 Doğrulaması: UA-1'in Devamı Değil

PDFlibPas, Delphi tarafında hedef parça değeri 2 ile TPDFlib.CheckFilePDFUACompliance üzerinden PDF/UA-2 (ISO 14289-2) dosyalarını doğrular; bu çağrı ayrı bir PDF/UA-2 profili çalıştırır: yapı rollerini PDF 2.0 ad alanları ve /RoleMapNS üzerinden çözer, kesilmiş ya da okunamayan girdiyi hata olarak raporlar ve asla tam sertifika iddiasında bulunmayan bir kapsam raporu döndürür

Son kısım göründüğünden daha önemli. Erişilebilirlik doğrulaması, yeşil onay işaretinin bir satın alma tablosuna kopyalanıp bir daha asla sorgulanmadığı bir alandır. Standardın yarısını sessizce atlayıp yine de "pass" yazdıran bir doğrulayıcı, hiç doğrulayıcı olmamasından kötüdür; çünkü bilinmeyeni yanlış bir bilinene çevirir. PDFlibPas tam tersini savunur: mekanik olarak denetlenebileni denetle, denetlenmeyeni yüksek sesle söyle ve her "bitiremedi" çıktısını başarı değil bulgu olarak ele al

PDF/UA-2 neden PDF/UA-1 kurallarıyla doğrulanamaz?

PDF/UA-2, parça numarası artırılmış PDF/UA-1 değildir. PDF/UA-1, PDF 1.7 ve tek bir düz role map üzerine oturur; PDF/UA-2 ise PDF 2.0 (ISO 32000-2) üzerine oturur; burada her yapı elemanı bir ad alanına ait olabilir ve her ad alanı kendi role map'ini taşır. Bir UA-2 dosyasına doğrultulmuş bir UA-1 denetleyicisi hem gerçek sorunları kaçırır hem de sahte sorunlar uydurur

Sahte olanlar utanç verici kısımdır. PDF/UA-1 doğrulayıcıları tipik olarak Note elemanlarının bir ID taşıması ve numarasız H başlığının nasıl kullanılabileceği konusunda kurallar uygular. Bu kuralların hiçbiri devredilemez. PDF 2.0 yapı ad alanında dipnotlar FENote ile ifade edilir ve başlıklar altı seviyelik bir tavan olmaksızın H1 ile Hn arasındadır. PDF/UA-2 bir adım öteye gider ve numarasız H rolünü tamamen yasaklar. Bu ağaca UA-1 başlık mantığını uygularsanız ya standardın izin verdiği şeylerden şikâyet edersiniz ya da yasakladığı tek şeye göz yumup geçersiniz

Bu yüzden PDFlibPas PDF/UA-2 profili ayrı bir kod yoludur, eskisinin üzerindeki bir bayrak değil. Ayrıca UA-1 madde numaralarını yeniden kullanmayı da reddeder. UA-1 denetleyicisiyle paylaşılan tanılar, UA-2 raporlarında ISO 14289-2'ye bağlanır ve bir madde numarası standart metnine karşı doğrulanmamışsa rapor, tahmin yürütmek yerine madde alanını boş bırakır. Boş bir madde, kendinden emin bir madde numarası kadar tatmin edici değildir; ama kimse eşlemeyi doğrulamamışken savunulabilir tek çıktı budur

PDFlibPas rolleri RoleMapNS üzerinden nasıl çözer?

PDFlibPas, ad alanları arasındaki /RoleMapNS zincirlerini izleyerek her yapı rolünü bilinen bir ad alanındaki standart bir role çözer ve özel bir rolde biten, döngüye giren ya da eşleme kurallarını bozan her zinciri raporlar. Bu, PDF/UA-2 yapı doğrulamasının çekirdeğidir; çünkü yardımcı teknoloji yalnızca standart rolleri anlar; özel bir /InvoiceLine, P ya da TR benzeri bir şeye varmadıkça hiçbir şey ifade etmez

Çözücü, elemanın /S adından ve /NS ad alanından yola çıkar. Ad alanı yoksa eleman örtük olarak PDF 1.7 standart ad alanındadır ve yapı ağacı kökündeki eski /RoleMap geçerlidir. Ad alanı varsa ad alanı sözlüğünün kendi /RoleMapNS'i geçerlidir ve bir eşleme, iki elemanlı bir dizi aracılığıyla farklı bir ad alanındaki bir role işaret edebilir. Buradan çıkan denetimler somuttur:

  • Bir yapı elemanından referans verilen ad alanı, geçerli bir /NS URI'sine sahip dolaylı bir sözlük olmalı ve yapı ağacı kökünün /Namespaces dizisinde listelenmelidir (tanı 10054)
  • Özel bir rol eninde sonunda PDF 1.7 ad alanındaki, PDF 2.0 ad alanındaki (http://iso.org/pdf2/ssn) veya MathML ad alanındaki standart bir role çözülmelidir; döngüsel zincirler ve çıkmaz yollar 10055 olarak raporlanır
  • Standart bir rol özel bir role yeniden eşlenemez ve bir rol kendi açık ad alanı içinde yeniden eşlenemez
  • Yapı kökü, PDF 2.0 ad alanında tam olarak bir Document elemanı içermelidir (10057) ve her elemanın /P'si gerçek ebeveynini işaret etmelidir (10058)
  • Numarasız bir H ya da bir PDF 2.0 rolüne eşlenmemiş eski bir PDF 1.7 Note'u, 10056 olarak raporlanır

Kendi araçlarınızı kurarken kopyalamaya değer bir ayrıntı: PDFlibPas yalnızca ağaçtan ulaşılabilenleri değil, bildirilen her eşlemeyi doğrular. Şu anda hiçbir elemanın kullanmadığı bir role map'teki bozuk bir girdi yine de gizli bir kusurdur; çünkü bir sonraki içerik güncellemesi onu kullanmaya başlayacaktır. MathML de dürüstçe ele alınır. MathML ad alanı geçerli bir çözüm hedefi olarak tanınır, ama MathML sözcük dağarcığının kendisi doğrulanmaz ve kapsam raporu bunu açıkça belirtir

Delphi'den PDF/UA-2 denetimi çalıştırmak

TPDFlib.CheckFilePDFUACompliance tek çağrılık giriş noktasıdır: dosyayı, şifreyi, hedef parçayı ve seçenekleri geçirirsiniz; karşılığında kodlanmış sorunları içeren bir string list handle alırsınız. Sıfır olan bir handle ile sıfıra eşit bir LastErrorCode, uygulanan denetimlerin hiçbir şey bulamadığı anlamına gelir; sıfırdan farklı bir LastErrorCode ise çağrının kendisinin başarısız olduğu anlamına gelir

var
  Lib: TPDFlib;
  Issues, I: Integer;
begin
  Lib := TPDFlib.Create;
  try
    // TargetPart: 0 = XMP pdfuaid:part'tan algıla, 1 = PDF/UA-1, 2 = PDF/UA-2
    // Options: 1 = ilk hatada dur, 0 = her sorunu topla
    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  // öğeler 1 tabanlıdır
        Writeln(Lib.GetStringListItem(Issues, I));
    finally
      Lib.ReleaseStringList(Issues);
    end;
  finally
    Lib.Free;
  end;
end;

Hedef parçayı bilinçli seçin. 0 hedefi, XMP meta verisinden pdfuaid:part okur ve profili ona göre seçer; bu, genel amaçlı bir gelen kutusu doğrulayıcısı için doğru tercihtir. Kendi çıktı hattınız için 2'yi açıkça geçirin. Üreticiniz kimliklendirmeyi yazmayı unuttuysa otomatik algılama UA-1 kurallarına döner ve yanlış standardı doğrularsınız; açık bir 2 ise eksik parça için tanı 10050, pdfuaid:rev değeri 2024 değilse 10051 ve etkin PDF sürümü 2.0 değilse 10052 üretir. Yazma tarafında TPDFlib.SetPDFUA2Mode bu kimliklendirmeyi yazar, sürümü 2.0'a çıkarır ve varsayılan olarak PDF 2.0 yapı ad alanını seçer; ad alanı modelinin kendisi PDF 2.0, PDF/A-4 ve PDF/UA-2 ad alanları anlatımında açıklanır

Doğrulayıcı bütçesi tükendiğinde ne olur?

PDFlibPas fail-closed davranır: PDF/UA-2 denetleyicisi bir gezinme sınırına, bir döngüye, bir ayrıştırıcı sınırına ya da açamadığı bir belgeye çarptığında bir tanı üretir ve tanısız bir sonuç asla geç sayılmaz. Tanı 10059 tam olarak bu "okuyucu bitiremedi" durumuna ayrılmıştır

Bütçeler açıktır ve kapsam JSON'unda yayımlanır: yapı derinliği 256, 100.000 yapı nesnesi ve herhangi bir role map zinciri boyunca 256 atlama. Bu sayılar oradadır; çünkü yapı ağaçları güvenilmeyen girdiden gelir. Düşmanca ya da sadece bozuk bir dosya, elemanları binlerce seviye derine yuvalayabilir, bir çocuğu bir ataya geri yönlendirebilir ya da yüzlerce ad alanı üzerinden zincirlenen bir role map kurabilir. Bütçesiz bir doğrulayıcı ya çöker ya da askıda kalır; bütçeli ama tanısız bir doğrulayıcı ise daha sinsi ve daha kötü bir şey yapar: erken durur, okuduğu kısımda hiçbir yanlış bulamaz ve başarı raporlar

Aynı ilke bir üst seviyede de geçerlidir. Temeldeki okuyucu, herhangi bir kural çalışmadan önce ayrıştırma kesildiğinde olabileceği gibi, 100'ün altında bir puan döndürür ama hiçbir sorun satırı vermezse PDFlibPas bir 10059 satırı ekler; böylece boş liste temiz bir sonuç sanılamaz. Denetim sırasında oluşan bir istisna da bir 10059 satırına dönüşür. Bu küçük bir kod miktarıdır ve doğrulama hatlarının sahiplerini kandırmasının en yaygın yolunu kapatır

PDF/A ile tek ayrıştırmayı paylaşmak ve rapor oluşturmak

Toplu işler için doğrulama hattı API'si bir dosyayı bir kez ayrıştırır ve paylaşılan ayrıştırmaya karşı birkaç denetim çalıştırır. RunPDFUAValidationPipelineTask bu ailenin PDF/UA üyesidir ve tek çağrılı fonksiyonla aynı hedef parça değerlerini alır; böylece PDF/A artı PDF/UA-2 preflight'ı, büyük bir belgeyi iki kez eksiksiz okumanın bedelini ödemez

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
    // ... iki handle'ı da önceki örnekte olduğu gibi inceleyin ve serbest bırakın ...
    Writeln('Parses: ', Lib.GetValidationPipelineParseCount(Pipe));
    // ComplianceTests: 1 = PDF/A, 2 = PDF/UA, 0 = her ikisi; ReportFormat 1 = JSON
    Json := Lib.CreateValidationPipelineReport(Pipe, 0, 0, 1);
  finally
    Lib.ReleaseValidationPipeline(Pipe);
  end;
end;

Yapılandırılmış rapor, dosya parça 2 olarak kimliklendiğinde erişilebilirlik bölümünü PDF/UA-2 ve ISO 14289-2 olarak etiketler ve her PDF/UA bölümü, gömülü kapsam nesnesiyle birlikte "fullCertification": false taşır. Metin preflight raporu, yalnızca uygulanan denetimlerin çalıştırıldığını ve tam erişilebilirlik sertifikasının ek doğrulama ile insan incelemesi gerektirdiğini belirten bir satır ekler. Daha geniş rapor biçimleri, kural ID'leri ve CI gating desenleri PDF/A ve PDF/UA preflight rehberinde anlatılır

Kapsam raporu gerçekte ne garanti eder?

TPDFlib.GetPDFUAReadValidationCoverageJSON tek bir şey garanti eder: PDF/UA-2 denetleyicisinin neyi incelediğinin ve neyi incelemediğinin tam listesini. Parça 2 için false'a sabitlenmiş fullCertification, bir checked dizisi, bir unverified dizisi ve gezinme sınırlarını döndürür. Bir dosyanın erişilebilir olduğunu garanti etmez ve hiçbir kod yolunun bunun tersini söyletemeyeceği şekilde tasarlanmıştır

var
  Coverage: WideString;
begin
  Coverage := Lib.GetPDFUAReadValidationCoverageJSON(2);
  // Doğrulama sonucunun yerine değil, yanında saklayın
  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;

Denetlenenler listesi kimliklendirmeyi (parça, revizyon, önek), etkin PDF sürümünü, başlık meta verisini, /MarkInfo'yu, DisplayDocTitle'ı, ad alanı referanslarını, role map çözümünü, belge kökünü, yapı ebeveynlerini, ağaç döngülerini ve H ile Note kurallarını kapsar. Doğrulanmamışlar listesi de aynı derecede özeldir: içerik işaretlemesi ve okuma sırası, yapı kapsaması, fontlar ve Unicode eşlemesi, ek açıklamalar ve formlar, doğal dil, alternatif açıklamalar, MathML sözcük dağarcığı ve insan erişilebilirlik incelemesi. Bunlardan birkaçı mekanik olarak karara bağlanabilir bile değildir. Hiçbir ayrıştırıcı, bir alt metnin grafiği gerçekten betimleyip betimlemediğini ya da okuma sırasının dinleyen biri için anlamlı olup olmadığını söyleyemez

Kapsam JSON'unu sonucun bir parçası gibi ele alın. Her doğrulama çalıştırmasıyla birlikte arşivleyin; bir denetçi belli bir tarihte "geçti" ifadesinin ne anlama geldiğini sorduğunda, bellekten ve bir sürüm numarasından yeniden kurmak yerine tam kapsamı teslim edebilirsiniz

veraPDF ile çapraz denetim

PDF/UA-2 çekirdeği, kendi ua2 profilini kullanan veraPDF 1.30.3 komut satırı doğrulayıcısına karşı çapraz denetlendi ve kapsam örtüştüğü yerde sonuçlar örtüşüyor. Bağımsız olarak üretilmiş geçerli bir çekirdek örneği her iki aracı da geçti; pdfuaid:rev değeri 2023 olan bir örnek ile numarasız H rolünü kullanan bir örnek her iki araçta da kaldı

Dördüncü örnek, üzerinde konuşulmaya değen olan. Hiç işaretlenmemiş çizim içeriği barındırıyordu ve veraPDF bunu işaretledi; PDFlibPas çekirdek denetimleri ise işaretlemedi, çünkü içerik işaretlemesi mevcut kapsamın dışında. Bu boşluk, content-tagging-and-reading-order maddesinin doğrulanmamışlar listesinin tepesinde olmasının tam nedeni. İkinci bir doğrulayıcı çalıştırmak ucuz bir sigortadır ve iki araç arasındaki anlaşmazlık, çoğu zaman her birinin neyi denetlediğinin sınırını bulmanın en hızlı yoludur. Aynı sorunun yazma tarafı için, baştan geçecek ağaçlar kurma konusunda işaretli PDF yapı ağacı rehberine bakın

FAQ

PDFlibPas bir dosyayı PDF/UA-2 uyumlu olarak sertifikalar mı?

Hayır. PDFlibPas, PDF/UA-2 için uygulanan makine denetimlerini çalıştırır ve false olan fullCertification değeriyle bir kapsam raporu döndürür; bu rapor hâlâ başka araçlara ya da insan incelemesine ihtiyaç duyan her alanı listeler

CheckFilePDFUACompliance'e hangi TargetPart değeri geçirilmeli?

Dosyanın PDF/UA-2 olması gerektiğini bildiğinizde 2 geçirin; böylece eksik kimliklendirme raporlanır. Parçayı XMP pdfuaid:part alanından otomatik algılamak için 0, PDF/UA-1 kurallarını zorlamak için 1 geçirin

PDF/UA-2 raporunda tanı 10059 ne anlama gelir?

Tanı 10059, doğrulayıcının işi tamamlayamadığı anlamına gelir: dosya ayrıştırılamadı ya da açılamadı, bir gezinme sınırı aşıldı, bir döngü bulundu ya da bir istisna oluştu. Bu her zaman bir hata olarak sayılır, asla geç sayılmaz

PDF/UA-2 doğrulaması, paylaşılan doğrulama hattı ve PDF 2.0 yazma API'leri, PDF/A preflight ve yapılandırılmış doğrulama raporlarıyla birlikte losLab PDF Library for Delphi içinde gelir