Technický článok

Výmena formulárových dát FDF, XFDF a XFA v Delphi

Knižnica losLab PDF Library prenáša formulárové dáta do a z PDF tromi rôznymi spôsobmi: FDF a XFDF pre hodnoty polí AcroForm, rovnaké dva formáty pre komentáre anotácií a celý balík XFA XDP zapísaný priamo do formulára. Vstupnými bodmi sú ExportFormDataToXFDF, ImportFormDataFromXFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF a SetXFAFromString, pričom každý z nich má súborový variant a reťazcový variant

Dôvodom, prečo existuje toľko metód, je to, že formulárové dáta PDF nie sú jednotnou záležitosťou. Vyplnený AcroForm obsahuje hodnoty polí, môže tiež niesť komentáre k recenzii a starší formulár XFA obsahuje celý popis aplikácie XML, ktorý nemá nič spoločné ani s jedným z nich. Knižnica losLab PDF Library zámerne uchováva tieto tri záležitosti v samostatných rozhraniach API, pretože ich zlúčenie by vynútilo nesprávny dátový model pre minimálne dve z nich. Rozhodnutie, ktorú rodinu potrebujete, je prvou voľbou dizajnu a zvyčajne sa vyrieši v momente, keď viete, čo prijímací systém na druhej strane skutočne spracúva

Aký je rozdiel medzi formulárovými dátami FDF, XFDF a XFA?

FDF a XFDF prenášajú rovnaké informácie v dvoch rôznych syntaxiach, zatiaľ čo XFA predstavuje samostatný svet. FDF je miniatúrny dokument so syntaxou PDF (ISO 32000-2 §12.7.8): pole /Fields slovníkov << /T (názov) /V (hodnota) >>, pričom reťazce sú escapované presne tak, ako sa escapujú literálové reťazce vo vnútri PDF. XFDF je XML forma rovnakých dát (ISO 19444), strom <fields>, ktorý Acrobat a väčšina backendov pre formuláre natívne čítajú a zapisujú. XFA nie je ani jedno: je to šablóna XML Forms Architecture a jej dáta, uložené ako XML Data Package (XDP), na ktorý PDF odkazuje z /AcroForm/XFA. Vyberte si FDF alebo XFDF, keď interagujete s hodnotami polí, a po XFA siahnite iba vtedy, keď udržiavate dokument, ktorý bol od začiatku vytvorený ako formulár XFA

V rámci FDF a XFDF kreslí losLab PDF Library druhú čiaru: hodnoty polí verzus komentáre anotácií. Rodina metód pre formulárové dáta (ExportFormDataToFDF, ImportFormDataFromFDF, ExportFormDataToXFDF, ImportFormDataFromXFDF) číta a zapisuje podstrom /Fields a ničoho iného sa nedotýka. Rodina pre anotácie (ExportAnnotationsToFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF, ImportAnnotationsFromXFDF) namiesto toho číta a zapisuje podstrom /Annots, čo je to, čo Acrobat označuje ako Export Comments (Exportovať komentáre). Tieto dve oblasti sa nikdy neprekrývajú, takže export hodnôt polí nezahrnie zatúlané poznámky z recenzie a import komentárov nenaruší hodnoty, ktoré už používateľ zadal. To, čo ovládací prvok (widget) urobí, keď naň kliknete alebo sa prepočíta, je opäť tretia záležitosť, ktorej sa venuje sprievodná poznámka o interaktívnych akciách formulárov a JavaScripte

Ako vyplniť PDF formulár z FDF alebo XFDF v Delphi?

Načítajte dokument, zavolajte jednu metódu importu a uložte. Metódy ImportFormDataFromXFDF a ImportFormDataFromFDF spracujú prichádzajúce formulárové dáta, priradia každú položku k poľu AcroForm podľa jeho plne kvalifikovaného názvu, nastavia hodnotu a vrátia počet skutočne aktualizovaných polí. Obe metódy aktualizujú iba tie polia, ktoré už v cieľovom PDF existujú; ani jedna z nich nevytvorí nové pole pre názov, ktorý formulár nedefinuje, čo zabraňuje tomu, aby zatúlaný alebo škodlivý dátový súbor nepozorovane rozšíril váš formulár

var
  Lib: TPDFlib;
  FieldsSet: Integer;
begin
  Lib := TPDFlib.Create;
  try
    Lib.LoadFromFile('application-blank.pdf', '');
    // XFDF produced by a case-management system, already UTF-8 on disk
    FieldsSet := Lib.ImportFormDataFromXFDF('applicant-1042.xfdf');
    if FieldsSet > 0 then
      Lib.SaveToFile('application-filled.pdf');
  finally
    Lib.Free;
  end;
end;

O tom, či netriviálne dáta prežijú prenos, rozhodujú dva detaily. Prvým je escapovanie: FDF ukladá hodnoty ako literálové reťazce PDF, takže hodnota obsahujúca zátvorku, spätné lomku alebo netlačiteľný bajt prichádza zabalená v oktálovom escapovaní definovanom v ISO 32000-2 §7.3.4.2 a losLab PDF Library toto escapovanie pri importe invertuje, takže zátvorky a lomky sa vrátia ako doslovné znaky, ktoré používateľ zadal. Druhým je kódovanie: súborové metódy zapisujú a čítajú XFDF and FDF v kódovaní UTF-8, čo deklarácia XFDF sľubuje a čo každá hodnota poľa mimo ASCII (meno s diakritikou, symbol meny, adresa CJK) potrebuje na úspešný prenos bez poškodenia. Ak si XFDF zostavujete sami, deklarujte UTF-8 a zapisujte v UTF-8 a import s tým bude súhlasiť

Hierarchické polia, voľby s viacerými hodnotami a formátovaný text

Hierarchické názvy polí sú prvým miestom, kde naivný exportér zlyhá. AcroForm odkazuje na vnorené pole pomocou bodkového názvu, ako napríklad Applicant.FullName, ale XFDF nevkladá tento bodkový reťazec do jediného atribútu name; ISO 19444 ho vnoruje ako <field name="Applicant"><field name="FullName">. Knižnica losLab PDF Library rozdelí bodkový názov na vnorené elementy <field> pri exporte a pri importe ich znova poskladá do plného názvu, takže oba smery zostávajú symetrické. Pri exporte tiež preskakuje neterminálne rodičovské polia, pretože rodičovský uzol v AcroForm nesie iba úroveň pomenovania a nemá vlastnú hodnotu; jeho emisia by vytvorila prázdnu <value></value>, ktorá nezodpovedá skutočnému formuláru. Zoznamy s viacnásobným výberom (multi-select list boxy) sú druhou pascou: pole výberu môže obsahovať niekoľko vybraných hodnôt naraz, čo XFDF vyjadruje ako opakované elementy <value> a FDF ako pole /V, pričom losLab PDF Library rozdelí pole na viacero hodnôt len vtedy, keď ide o skutočný viacnásobný výber, takže bežné viacriadkové textové pole si zachová svoje zalomenia riadkov namiesto toho, aby sa roztrieštilo na falošné hodnoty

Formátovaný text (rich text) je tretí a je to ten, v ktorom ľudia najčastejšie robia chyby. Pole s formátovaním ukladá svoje značky v položke RV ako podstrom XHTML a XFDF ich prenáša v <value-richtext>. Knižnica losLab PDF Library zapisuje tento podstrom ako živý XML fragment namiesto jeho escapovania, takže následný nástroj číta skutočný formátovaný text namiesto reťazca viditeľných značiek; pri importe zachováva pôvodný podstrom RV a stále aplikuje obyčajnú <value> do V. Ak pole ponúka oboje, obyčajná hodnota vyhráva pre V a formátovaný text sa prenáša popri nej v RV, čo je pravidlo interoperability, ktoré bráni tomu, aby import formátovaného textu ticho prepísal hodnotu, ktorú už iný nástroj nastavil. Ak váš formátovaný text slúži na sprostredkovanie štruktúry dokumentu asistenčným technológiám, zaobchádzajte s ním rovnako, ako by ste zaobchádzali s poradím čítania popísaným v poznámke o tagovanom PDF a štruktúre prístupnosti

var
  Lib: TPDFlib;
const
  XFDF =
    '<?xml version="1.0" encoding="UTF-8"?>' +
    '<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">' +
    '<fields>' +
    '  <field name="Applicant">' +
    '    <field name="FullName"><value>Alice Example</value></field>' +
    '  </field>' +
    '  <field name="Skills">' +
    '    <value>Delphi</value><value>PDF</value>' +
    '  </field>' +
    '  <field name="Notes">' +
    '    <value>See attachment</value>' +
    '    <value-richtext><body><p>See <b>attachment</b></p></body></value-richtext>' +
    '  </field>' +
    '</fields></xfdf>';
begin
  Lib := TPDFlib.Create;
  try
    Lib.LoadFromFile('intake.pdf', '');
    // Applicant.FullName reassembles; Skills fills the /V + /I arrays;
    // Notes gets V from <value> and RV from <value-richtext>
    Lib.ImportFormDataFromXFDFString(XFDF);
    Lib.SaveToFile('intake-filled.pdf');
  finally
    Lib.Free;
  end;
end;

Ako prenášať komentáre anotácií tam a späť ako FDF alebo XFDF?

Komentáre sa prenášajú v rámci anotačnej rodiny metód a podporovaná podmnožina je zámerne malá. ExportAnnotationsToXFDF a ImportAnnotationsFromXFDF spolu so svojimi náprotivkami FDF prenášajú textové značky s poľami, ktoré sa skutočne úspešne prenášajú: podtyp anotácie, jej obdĺžnik, index stránky od 0, autor v T, predmet v Subj, čistý text Contents a farba, ktorá mapuje PDF /C DeviceRGB trojicu do a z atribútu XFDF #RRGGBB. Import prijíma iba známe názvy elementov a preskakuje každú položku, ktorej stránka je mimo rozsahu alebo ktorej obdĺžnik chýba, takže ručne upravené alebo cudzie XFDF nemôže vložiť nesprávne formátovanú anotáciu do dokumentu. To, čo táto podmnožina zatiaľ neprenáša, stojí za to uviesť otvorene: formátovaný textový obsah (RC), vyskakovacie okná (popupy), quadpointy, zoznamy atramentu (ink listy), vrcholy (vertices) a zapečené toky vzhľadu (appearance streams) sú momentálne mimo rozsahu, takže geometria zvýraznenia a vlastný vzhľad pečiatky neprežijú túto cestu. Ak chcete potvrdiť, čo skutočne pribudlo, prejdite anotácie stránky alebo širší strom prvkov popísaný v časti vyhľadávanie textu a enumerácia prvkov stránky

var
  Src, Dest: TPDFlib;
  Xfdf: WideString;
begin
  Src := TPDFlib.Create;
  Dest := TPDFlib.Create;
  try
    Src.LoadFromFile('reviewed.pdf', '');
    Xfdf := Src.ExportAnnotationsToXFDFString;   // <annots> subset only

    Dest.LoadFromFile('clean-copy.pdf', '');     // pages must line up by index
    Dest.ImportAnnotationsFromXFDFString(Xfdf);
    Dest.SaveToFile('clean-copy-commented.pdf');
  finally
    Dest.Free;
    Src.Free;
  end;
end;

Zápis celého balíka XFA XDP pomocou SetXFAFromString

XFA je anomália a SetXFAFromString je spôsob, ako zapísať celú vec naraz. Metóda prijíma kompletný XML Data Package, dokument <xdp:xdp> so svojimi balíkmi template a datasets, a ukladá ho ako stream, na ktorý odkazuje /AcroForm/XFA. Knižnica losLab PDF Library vytvorí kontajner AcroForm na požiadanie, keď dokument žiadny nemá, takže nemusíte pridávať zbytočné pole len preto, aby malo XFA na čom visieť, a zahodí akýkoľvek spracovaný stav XFA, ktorý uchovávala, takže neskoršie čítanie odráža balík, ktorý ste práve zapísali, a nie starú medzipamäť. Keďže balík XFA je XML a nemusí byť nutne v kódovania UTF-8, knižnica deteguje značku poradia bajtov (BOM) UTF-16 a pred spracovaním balík správne dekóduje, čo je dôležité pre balíky vytvorené nástrojmi, ktoré predvolene používajú UTF-16

Akonáhle je balík na svojom mieste, GetXFAFormFieldValue a SetXFAFormFieldValue pristupujú k jednotlivým poliam prostredníctvom ich cesty Scripting Object Model (SOM). Knižnica losLab PDF Library prijíma štandardné korene SOM, ako aj holé relatívne cesty, takže form1.FullName, $data.form1.FullName a xfa.datasets.data.form1.FullName sa všetky vyhodnotia na rovnaký dátový uzol, a strana šablóny (template) rovnako akceptuje $template a xfa.template. Táto tolerancia je dôležitá, keď sú cesty SOM generované iným systémom, ktorý vždy odosiela plne kvalifikovaný formulár

var
  Lib: TPDFlib;
const
  Xdp =
    '<?xml version="1.0" encoding="UTF-8"?>' +
    '<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">' +
    '  <template xmlns="http://www.xfa.org/schema/xfa-template/3.3/">' +
    '    <subform name="form1">' +
    '      <field name="FullName"><ui><textEdit/></ui></field>' +
    '    </subform>' +
    '  </template>' +
    '  <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">' +
    '    <xfa:data><form1><FullName>Alice Example</FullName></form1></xfa:data>' +
    '  </xfa:datasets>' +
    '</xdp:xdp>';
begin
  Lib := TPDFlib.Create;
  try
    Lib.SetXFAFromString(Xdp, 0);      // creates the AcroForm container if none exists
    // read back through the data DOM with an SOM path
    if Lib.GetXFAFormFieldValue('form1.FullName') = 'Alice Example' then
      Lib.SetXFAFormFieldValue('form1.FullName', 'Bob Example');
    Lib.SaveToFile('xfa-packet.pdf');
  finally
    Lib.Free;
  end;
end;

Úprimné zhrnutie je, že hodnoty polí sa plne prenášajú cez FDF a XFDF, vrátane hierarchie, viacnásobného výberu a formátovaného textu; komentáre anotácií sa prenášajú ako definovaná podmnožina textových značiek s jasnými medzerami; a XFA sa zapisuje a číta ako celý balík s dodatočným prístupom SOM pre jednotlivé polia. Prispôsobte formát príjemcovi, deklarujte UTF-8 pre všetko, čo vytvárate ručne, a pamätajte, že importné metódy sa dotýkajú iba polí a anotácií, ktoré už zodpovedajú dokumentu. Metódy pre formulárové dáta, anotácie a XFA opísané v tomto dokumente sú súčasťou knižnice losLab PDF Library pre Delphi a C++Builder, ktorej referenčná príručka obsahuje úplný zoznam parametrov pre každý vstupný bod exportu a importu