מאמר טכני

פלט PDF 2.0, PDF/A-4 ו-PDF/UA-2 עם HotPDF בדלפי

HotPDF כותבת מסמכי PDF 2.0 מקוריים מדלפי ו-C++Builder, כולל שלושת פרופילי הארכיון PDF/A-4 ופלט נגיש PDF/UA-2 עם אלמנטי מבנה בעלי מרחב שמות. בחירתם היא עניין של שני מאפיינים, אך התקנים שמאחורי אותם מאפיינים השתנו יותר ממה שמספר הגרסה מרמז: PDF/A-4 ויתר על אותיות ההתאמה שכולם למדו עם PDF/A-2, ו-PDF/UA-2 הציג מרחבי שמות מבנה שלמסמך חלק 1 מעולם לא היו

מאמר זה מכסה מה באמת משתנה בקובץ שנוצר, ואילו טעויות HotPDF הופכת לחריג ב-EndDoc במקום למסמך שנכשל בתיקוף אצל הלקוח

כיצד זיהוי PDF/A-4 שונה מחלק 2 ו-3

PDF/A-4 מזהה את עצמו במספר חלק ושנת מהדורה, ללא אות התאמה לחלק הבסיסי. הגדר את PDFACompliance ל-'4' ו-HotPDF פולטת pdfaid:part=4 עם pdfaid:rev=2020 וללא כניסת pdfaid:conformance כלל. האות לא אבדה — לחלק 4 אין רמות A/B/U, מפני שהדרישות שנהגו להפריד ביניהן קופלו לתוך החלק הבסיסי

שתי הרחבות שומרות על אות. '4E' בוחר PDF/A-4e למסמכי הנדסה ופולט התאמה E, שמתירה את נתיבי ההערות 3D ו-RichMedia ששאר הפרופילים אוסרים. '4F' בוחר PDF/A-4f ופולט התאמה F, שמתירה קובץ מוטמע בכל פורמט. כל השלושה כופים כותרת PDF 2.0, דורשים את בדיקות output intent והמטא-נתונים הרגילות של PDF/A, ואוסרים הצפנה — קובץ ארכיוני מוצפן הוא סתירה שהתקן אינו מקבל

var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'invoice-archive.pdf';
    Pdf.PDFACompliance := '4F';   // PDF/A-4f: associated files of any format
    Pdf.BeginDoc;
    Pdf.CurrentPage.SetFont('Arial', [], 11);
    Pdf.CurrentPage.TextOut(50, 760, 0, 'Invoice 2026-0731');
    Pdf.AddPDFAssociatedFile('invoice.xml', 'text/xml',
      'Structured invoice data', 'Data', LoadInvoiceBytes);
    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

AddPDFAssociatedFile מטמיע את הקובץ, בונה את FileSpec שלו עם /AFRelationship, ורושם אותו גם במערך /AF של הקטלוג וגם בעץ השמות EmbeddedFiles. שני הרישומים נדרשים; קובץ הרשום רק באחד מהם הוא הסיבה השכיחה ביותר לכך שחשבונית היברידית עוברת בדיקת עין מהירה ונכשלת במאמת אמיתי. מחרוזת הקשר מקבלת Source, Data, Alternative, Supplement או Unspecified, והפרופיל הפעיל חייב להיות PDF/A-3, PDF/A-4e או PDF/A-4f — פרופיל הבסיס חלק 4 אינו מקבל קבצים משויכים. השם הישן AddPDFA3AssociatedFile עדיין עובד לקוד קיים

מה PDF/UA-2 דורש ש-PDF/UA-1 לא דרש

PDF/UA-2 כופה PDF 2.0 ופולט pdfuaid:part=2 עם pdfuaid:rev=2024, ומכניס מרחבי שמות לתוך עץ המבנה. למסמך חלק 1 היה אוצר מילים אחד שטוח של תפקידים סטנדרטיים. מסמך חלק 2 יכול לשאת תפקידים מותאמים אישית כל עוד כל אחד מהם שייך למרחב שמות מוצהר, שזה מה שהופך תיוג ספציפי-לתחום לקריא על ידי טכנולוגיה מסייעת במקום ניחוש

שתי שיטות מיישמות זאת. RegisterStructureNamespace יוצרת או משתמשת במילון /Type /Namespace עקיף ורושמת אותו ב-StructTreeRoot /Namespaces, ומחזירה את המילון כך שתוכל לעשות בו שימוש חוזר. AddStructureElementNS יוצר אלמנט מבנה שהכניסה /NS שלו מצביעה על אותו מילון, שזה מה שמרשה שם תפקיד מחוץ לסט הסטנדרטי. קריאות חוזרות עם אותו URI משתמשות במילון אחד במקום לצבור כפילויות

var
  Root: THPDFDictionaryObject;
begin
  Pdf.PDFUACompliance := True;
  Pdf.PDFUAPart := 2;             // part 2 forces PDF 2.0
  Pdf.Lang := 'en-US';
  Pdf.BeginDoc;
  Root := Pdf.AddStructureElement('Document', nil);
  Pdf.AddStructureElementNS('WidgetGroup',
    'https://example.com/ns/widgets', Root);
  Pdf.EndDoc;
end;

Lang אינה קישוט כאן. מסמך מתויג ללא הצהרת שפה טבעית משאיר קורא מסך לנחש הגייה, ו-PDF/UA מתייחס להשמטה כאל ליקוי ולא כהעדפה

אילו שגיאות מבנה EndDoc תופס?

ארבע, וכל אחת מתאימה למסמך שאחרת היה מגיע שבור למאמת. שורש המבנה חייב להכיל בדיוק אלמנט Document אחד ברמה העליונה. כל מילון מרחב-שמות חייב להיות עקיף, מוקלד כ-Namespace, ולשאת URI ייחודי לא-ריק. כל הפניית /NS של אלמנט מבנה חייבת להיפתר למילון שרשום בפועל במערך /Namespaces של השורש. ותפקיד ללא מרחב שמות חייב להיות תפקיד סטנדרטי של PDF 2.0 או להיפתר דרך RoleMap

אלה נורים ב-EndDoc מפני שזו הרגע האחרון שבו העץ כולו קיים בזיכרון והרגע הראשון שהוא שלם. תפיסתן מוקדם יותר הייתה אומרת דחיית מצבי ביניים תקפים; תפיסתן מאוחר יותר הייתה אומרת לא לתפוס אותן כלל. ההשלכה המעשית עבור הקוד שלך היא שבאג מבנה עולה על פני השטח בסוף הייצור עם הודעה שמזהה את הבעיה, במקום לעלות שבועות אחר כך כדוח veraPDF שמישהו מעביר מלקוח

התפקידים של PDF 2.0 שכדאי להכיר

enum התפקידים המוקלד רוכש את DocumentFragment, Aside, Title, FENote, Sub, Em, Strong ו-Artifact. שלושה מאלה משנים כיצד אתה מתייג מסמכי עסקים רגילים. Aside סוף-סוף נותן לסרגלי צד ולציטוטים שלוף בית שאינו Sect שנעשה בו שימוש לרעה. FENote מסמן הערות שוליים והערות סיום כמו שהן, כך שקורא יכול להציע אותן במקום לשלב אותן עם טקסט הגוף. Em ו-Strong מחליפים את ניחוש הסמנטי שבא מתיוג הדגשה כעיצוב ברמת span

העומס-היתר של מחרוזת מקבל בנוסף את הצורה הפתוחה Hn, כולל H7 ומעבר לו. PDF 1.7 עצר ב-H6, שכפה על מסמכים טכניים עמוקים לשטח את המתאר שלהם או לעשות שימוש חוזר ברמות. אם אתה מייצר מסמכי תקנים, קודים משפטיים או קטלוגי חלקים, זה לבד יכול להיות הסיבה להעביר פלט ל-PDF 2.0

מה לבדוק לפני החלפת פלט הייצור

PDF 2.0 הוא שינוי כותרת עם זנב ארוך. כלי בליעת ארכיון ישנים יותר, חלק מה-RIP של דפוס ומספר מפתיע של קוראי line-of-business מקבלים רק עד PDF 1.7, והם נכשלים על הכותרת ולא על שום דבר שעשית לא נכון. לפני החלפה, יש לאשר את מערכות הצריכה, ולזכור שבחירת פרופיל PDF/A-4 בוחרת PDF 2.0 בין אם ביקשת זאת ובין אם לא

סדר בטוח הוא להשאיר PDF/A-3 למסמכים שיוצאים החוצה לקוראים לא-מוכרים, להשתמש ב-PDF/A-4f לארכיונים פנימיים שבהם אתה שולט בבליעה, ולאמץ PDF/UA-2 רק היכן שהמדיניות נגישות מציינת אותו בשם. אם אתה עובד קודם דרך הצד הארכיוני, המדריכים לתיקוף PDF/A, PDF/X ו-PDF/UA ולחשבוניות היברידיות ZUGFeRD ו-Factur-X על PDF/A-3 מכסים את בחירות הפרופיל שחשובות לפני מספר הגרסה, וההערות על דיווח preflight אוטומטי מראות כיצד להפוך את פסק הדין לחלק מה-build שלך במקום צעד ידני

HotPDF מובילה את כל משטח ה-authoring של PDF 2.0 כקוד VCL מקורי לדלפי ו-C++Builder, כך שפלט PDF/A-4 ו-PDF/UA-2 אינם דורשים מנוע חיצוני או הפצה מחדש — דף רכיב HotPDF מפרט את הפרופילים הנתמכים ואת גרסאות RAD Studio