مقاله فنی

تبادل داده‌های فرم FDF، XFDF و XFA در دلفی

کتابخانه PDF losLab داده‌های فرم را به سه روش مختلف به درون و بیرون یک فایل PDF منتقل می‌کند: FDF و XFDF برای مقادیر فیلدهای AcroForm، همین دو فرمت برای یادداشت‌های توضیحی (annotation comments)، و یک بسته کامل XFA XDP که مستقیماً در فرم نوشته می‌شود. متدهای ExportFormDataToXFDF، ImportFormDataFromXFDF، ImportAnnotationsFromFDF، ExportAnnotationsToXFDF و SetXFAFromString نقاط ورود هستند و هر یک از آن‌ها دارای یک نسخه فایل و یک نسخه رشته‌ای (string) می‌باشند

دلیل وجود متدهای بسیار این است که داده‌های فرم PDF یک چیز واحد نیستند. یک AcroForm پر شده دارای مقادیر فیلد است، همچنین ممکن است حاوی یادداشت‌های بازبینی باشد، و یک فرم قدیمی XFA یک توصیف کامل از برنامه XML را در خود جای داده است که ارتباطی با هیچ‌کدام از آن دو ندارد. کتابخانه PDF losLab عمداً این سه دغدغه را در APIهای مجزا نگه می‌دارد، زیرا ادغام آن‌ها مدل داده‌ای نادرستی را به حداقل دو مورد از آن‌ها تحمیل می‌کرد. تصمیم‌گیری در مورد اینکه به کدام خانواده نیاز دارید اولین انتخاب طراحی است و معمولاً به محض اینکه بدانید سیستم دریافت‌کننده در طرف مقابل دقیقاً چه چیزی را مصرف می‌کند، مشخص می‌شود

تفاوت بین داده‌های فرم FDF، XFDF و XFA چیست؟

قالب‌های FDF و XFDF اطلاعات یکسانی را در دو نحو (syntax) متفاوت حمل می‌کنند، در حالی که XFA دنیای مجزایی است. FDF یک سند مینیاتوری با نحو PDF است (ISO 32000-2 §12.7.8): یک آرایه /Fields از دیکشنری‌های << /T (name) /V (value) >>، با رشته‌هایی که دقیقاً به همان روشی که رشته‌های تحت‌اللفظی در داخل PDF گریز داده می‌شوند (escaped)، نوشته شده‌اند. XFDF شکل XML همان داده‌ها است (ISO 19444)، یک درخت <fields> که آکروبات و اکثر بخش‌های پشتیبان فرم‌ها به صورت بومی آن را می‌خوانند و می‌نویسند. XFA هیچ‌کدام نیست: این یک قالب ساختار فرم‌های XML (مخفف XML Forms Architecture) به همراه داده‌های آن است که به عنوان یک بسته داده XML (مخفف XDP) ذخیره می‌شود و PDF از بخش /AcroForm/XFA به آن ارجاع می‌دهد. هنگامی که روی مقادیر فیلدها کار می‌کنید، FDF یا XFDF را انتخاب کنید و تنها زمانی به سراغ XFA بروید که در حال نگهداری سندی هستید که از ابتدا به عنوان یک فرم XFA طراحی شده است

در درون FDF و XFDF، کتابخانه PDF losLab خط دوم را ترسیم می‌کند: مقادیر فیلدها در مقابل یادداشت‌های توضیحی. خانواده داده‌های فرم (ExportFormDataToFDF، ImportFormDataFromFDF، ExportFormDataToXFDF، ImportFormDataFromXFDF) زیردرخت /Fields را می‌خوانند و می‌نویسند و به چیز دیگری دست نمی‌زنند. در مقابل، خانواده یادداشت‌ها (ExportAnnotationsToFDF، ImportAnnotationsFromFDF، ExportAnnotationsToXFDF، ImportAnnotationsFromXFDF) زیردرخت /Annots را می‌خوانند و می‌نویسند، که همان چیزی است که آکروبات از آن به عنوان Export Comments یاد می‌کند. این دو هرگز با هم هم‌پوشانی ندارند، بنابراین صادر کردن مقادیر فیلدها یادداشت‌های بازبینی متفرقه را جمع‌آوری نمی‌کند و وارد کردن یادداشت‌ها، مقادیری را که کاربر قبلاً تایپ کرده است، به هم نمی‌ریزد. اینکه یک ویجت هنگام کلیک شدن یا محاسبه مجدد چه کاری انجام می‌دهد، سومین دغدغه است که در یادداشت راهنمای اکشن‌های تعاملی فرم و جاوا اسکریپت بررسی شده است

چگونه یک فرم PDF را از FDF یا XFDF در دلفی پر کنیم؟

سند را بارگذاری کنید، یکی از متدهای وارد کردن (import) را فراخوانی کنید و ذخیره نمایید. هر یک از متدهای ImportFormDataFromXFDF و ImportFormDataFromFDF داده‌های فرم ورودی را تجزیه می‌کنند، هر ورودی را بر اساس نام کاملاً واجد شرایط آن با یک فیلد AcroForm مطابقت می‌دهند، مقدار را تنظیم کرده و تعداد فیلدهایی را که واقعاً به‌روزرسانی شده‌اند برمی‌گردانند. هر دو متد فقط فیلدهایی را به‌روزرسانی می‌کنند که از قبل در PDF مقصد وجود دارند؛ هیچ‌کدام برای نامی که فرم تعریف نکرده است فیلدی ایجاد نمی‌کنند، که این کار مانع از آن می‌شود که یک فایل داده‌ای متفرقه یا مخرب به طور ناخواسته فرم شما را گسترش دهد

دو جزئیات تعیین می‌کنند که آیا داده‌های غیرساده از این مسیر سالم عبور می‌کنند یا خیر. اولین مورد گریزدهی (escaping) است: FDF مقادیر را به عنوان رشته‌های تحت‌اللفظی PDF ذخیره می‌کند، بنابراین مقداری که حاوی پرانتز، بک‌اسلش یا بایت غیرقابل چاپ باشد، در گریزدهی هشت‌هشتی (octal escaping) تعریف‌شده در استاندارد ISO 32000-2 §7.3.4.2 قرار می‌گیرد، و کتابخانه PDF losLab این گریزدهی را در هنگام ورود معکوس می‌کند تا پرانتزها و اسلش‌ها به عنوان نویسه‌های تحت‌اللفظی که کاربر تایپ کرده است بازگردند. مورد دوم رمزگذاری (encoding) است: متدهای مبتنی بر فایل، XFDF و FDF را به صورت UTF-8 می‌نویسند و می‌خوانند، که این همان چیزی است که اعلان XFDF وعده می‌دهد و هر مقدار فیلد غیر ASCII (یک نام دارای علامت، یک نماد ارز، یا یک آدرس CJK) برای انتقال رفت و برگشتی بدون خرابی به آن نیاز دارد. اگر خودتان XFDF را می‌سازید، آن را به عنوان UTF-8 اعلام کنید و به صورت UTF-8 بنویسید تا فرآیند ورود با آن همخوانی داشته باشد

فیلدهای سلسله‌مراتبی، گزینه‌های چندمقداری و متن غنی

نام فیلدهای سلسله‌مراتبی اولین جایی است که یک صادرکننده ساده‌لوح خراب می‌شود. AcroForm یک فیلد تو در تو را با یک عنوان کامل نقطه‌دار مانند Applicant.FullName آدرس‌دهی می‌کند، اما XFDF این رشته نقطه‌دار را در یک ویژگی تک‌نام قرار نمی‌دهد؛ استاندارد ISO 19444 آن را به صورت <field name="Applicant"><field name="FullName"> تو در تو قرار می‌دهد. کتابخانه PDF losLab عنوان نقطه‌دار را در هنگام صادر کردن به عناصر تو در توی <field> تقسیم می‌کند و در هنگام وارد کردن، عناصر تو در تو را دوباره به عنوان کامل متصل می‌کند تا هر دو جهت متقارن بمانند. در هنگام صادر کردن، این کتابخانه همچنین فیلدهای والد غیرنهایی را نادیده می‌گیرد، زیرا یک گره والد در یک AcroForm فقط سطح نام‌گذاری را حمل می‌کند و هیچ مقداری از خود ندارد؛ صادر کردن آن یک <value></value> خالی ایجاد می‌کند که با فرم واقعی مطابقت ندارد. کادرهای لیست چندگزینه‌ای (multi-select list boxes) دومین تله هستند: یک فیلد انتخاب می‌تواند چندین مقدار انتخاب‌شده را به طور همزمان نگه دارد، که XFDF آن را با عناصر تکراری <value> بیان می‌کند و FDF آن را به صورت یک آرایه /V نشان می‌دهد، و کتابخانه PDF losLab تنها زمانی یک فیلد را به چندین مقدار تقسیم می‌کند که واقعاً یک انتخاب چندگزینه‌ای باشد، به طوری که یک فیلد متنی چندخطی معمولی خطوط شکسته خود را حفظ می‌کند و به مقادیر جعلی تبدیل نمی‌شود

متن غنی (rich text) مورد سوم است و موردی است که مردم بیشتر اوقات آن را اشتباه می‌گیرند. یک فیلد فرمت‌بندی‌شده، نشانه‌گذاری خود را در ورودی RV به عنوان یک زیردرخت XHTML ذخیره می‌کند و XFDF آن را در <value-richtext> حمل می‌نماید. کتابخانه PDF losLab آن زیردرخت را به عنوان یک قطعه XML زنده می‌نویسد تا اینکه آن را گریزدهی کند، بنابراین یک ابزار پایین‌دست متن غنی واقعی را به جای رشته‌ای از تگ‌های مرئی می‌خواند؛ در هنگام ورود، این کتابخانه زیردرخت خام RV را حفظ می‌کند و همچنان مقدار ساده <value> را به V اعمال می‌نماید. در جایی که یک فیلد هر دو را ارائه می‌دهد، مقدار ساده برای V اولویت دارد و متن غنی در کنار آن در RV قرار می‌گیرد، که این قانون قابلیت همکاری است که مانع از آن می‌شود تا وارد کردن متن غنی به طور ناخواسته مقداری را که ابزار دیگری قبلاً تنظیم کرده است، بازنویسی کند. هنگامی که متن غنی شما برای انتقال ساختار سند به فناوری‌های کمکی وجود دارد، با آن همان رفتاری را داشته باشید که با ترتیب خواندن بحث‌شده در یادداشت مربوط به ساختار دسترسی‌پذیری و PDF تگ‌شده انجام می‌دهید

چگونه یادداشت‌های بازبینی را به عنوان FDF یا XFDF انتقال دهیم؟

یادداشت‌ها در خانواده یادداشت‌های توضیحی حرکت می‌کنند و زیرمجموعه پشتیبانی‌شده عمداً کوچک است. ExportAnnotationsToXFDF و ImportAnnotationsFromXFDF به همراه همتایان FDF خود، نشانه‌گذاری‌های متنی را به همراه فیلدهایی که واقعاً بدون مشکل رفت و برگشت می‌کنند حمل می‌کنند: نوع فرعی یادداشت، مستطیل آن، ایندکس صفحه مبتنی بر ۰، نویسنده در T، موضوع در Subj، محتوای ساده Contents، و رنگ، که سه‌گانه DeviceRGB در PDF /C را به یک ویژگی XFDF #RRGGBB نگاشت می‌کند. فرآیند ورود فقط نام عناصر شناخته‌شده را می‌پذیرد و از هر ورودی که صفحه آن خارج از محدوده باشد یا مستطیل آن وجود نداشته باشد چشم‌پوشی می‌کند، بنابراین یک XFDF دستی یا خارجی نمی‌تواند یک یادداشت بدشکل را به سند اضافه کند. آنچه این زیرمجموعه هنوز حمل نمی‌کند ارزش بیان صریح دارد: محتوای متن غنی (RC), پاپ‌آپ‌ها، نقاط چهارگانه (quadpoints)، لیست‌های جوهر (ink lists)، رئوس و جریان‌های ظاهری رندرشده (baked appearance streams) در حال حاضر خارج از محدوده هستند، بنابراین هندسه هایلایت و ظاهر تمبرهای سفارشی از این مسیر عبور نخواهند کرد. برای تایید آنچه واقعاً ثبت شده است، یادداشت‌های صفحه یا درخت عناصر گسترده‌تر پوشش داده‌شده در جستجوی متن و شمارش عناصر صفحه را بررسی کنید

نوشتن یک بسته کامل XFA XDP با SetXFAFromString

قالب XFA یک استثنا است و SetXFAFromString روشی است که با آن کل بسته را به یکباره می‌نویسید. این متد یک بسته داده کامل XML (مخفف XML Data Package)، یعنی سند <xdp:xdp> را با بسته‌های الگو و مجموعه‌داده‌های آن دریافت کرده و به عنوان جریانی ذخیره می‌کند که از بخش /AcroForm/XFA به آن ارجاع داده می‌شود. کتابخانه PDF losLab در صورت نبود کانتینر AcroForm، آن را در زمان تقاضا ایجاد می‌کند، بنابراین نیازی نیست یک فیلد بیهوده اضافه کنید تا فقط برای XFA جایی برای اتصال ایجاد شود، و هر وضعیت XFA تجزیه‌شده‌ای را که نگه داشته بود دور می‌اندازد تا خواندن بعدی منعکس‌کننده بسته‌ای باشد که به تازگی نوشته‌اید، نه یک حافظه پنهان قدیمی. از آنجا که یک بسته XFA از نوع XML است و لزوماً UTF-8 نیست، کتابخانه علامت ترتیب بایت (BOM) در UTF-16 را شناسایی کرده و بسته را قبل از تجزیه به درستی رمزگشایی می‌کند، که این موضوع برای بسته‌های تولید شده توسط ابزارهایی که به طور پیش‌فرض روی UTF-16 تنظیم شده‌اند اهمیت دارد

هنگامی که بسته در جای خود قرار گرفت، متدهای GetXFAFormFieldValue و SetXFAFormFieldValue فیلدهای فردی را از طریق مسیر مدل شیء اسکریپت‌نویسی (SOM) آن‌ها آدرس‌دهی می‌کنند. کتابخانه PDF losLab ریشه‌های استاندارد SOM و همچنین مسیرهای نسبی ساده را می‌پذیرد، بنابراین مسیرهای form1.FullName، $data.form1.FullName و xfa.datasets.data.form1.FullName همگی به یک گره داده یکسان منتهی می‌شوند و بخش الگو نیز $template و xfa.template را به همین ترتیب می‌پذیرد. این تساهل زمانی اهمیت پیدا می‌کند که مسیرهای SOM توسط سیستم دیگری تولید شوند که همیشه فرم کاملاً واجد شرایط را صادر می‌کند

خلاصه واقع‌بینانه این است که مقادیر فیلدها به طور کامل از طریق FDF و XFDF منتقل می‌شوند، از جمله ساختار سلسله‌مراتبی، انتخاب چندگانه و متن غنی؛ یادداشت‌های بازبینی به عنوان یک زیرمجموعه نشانه‌گذاری متنی تعریف‌شده با شکاف‌های مشخص منتقل می‌شوند؛ و XFA به عنوان یک بسته کامل با دسترسی SOM برای هر فیلد نوشته و خوانده می‌شود. قالب را با مصرف‌کننده مطابقت دهید، برای هر چیزی که به صورت دستی می‌سازید UTF-8 اعلام کنید، و به یاد داشته باشید که متدهای وارد کردن فقط فیلدها و یادداشت‌هایی را لمس می‌کنند که از قبل با سند همخوانی دارند. متدهای داده‌های فرم، یادداشت‌ها و XFA توصیف‌شده در اینجا بخشی از losLab PDF Library برای دلفی و سی‌پلاس‌پلاس‌بیلدر هستند که راهنمای مرجع آن فهرست کامل پارامترها را برای هر نقطه ورود صادر کردن و وارد کردن به همراه دارد