losLab PDF Library siirtää lomaketietoja PDF-tiedostoon ja sieltä pois kolmella eri tavalla: FDF ja XFDF AcroForm-kenttien arvoille, samat kaksi muotoa huomautuskommenteille ja kokonainen XFA XDP -paketti, joka kirjoitetaan suoraan lomakkeeseen. ExportFormDataToXFDF, ImportFormDataFromXFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF ja SetXFAFromString ovat aloituspisteitä, ja jokaisesta niistä on olemassa tiedosto- ja merkkijonovariantti
Syy moniin menetelmiin on se, että PDF-lomakkeen tiedot eivät ole vain yhtä asiaa. Täytetyllä AcroForm-lomakkeella on kenttäarvoja, se voi myös sisältää tarkistuskommentteja, ja vanha XFA-lomake sisältää kokonaisen XML-sovelluskuvauksen, jolla ei ole mitään tekemistä kummankaan edellisen kanssa. losLab PDF Library pitää nämä kolme asiaa erillisissä rajapinnoissa tarkoituksella, koska niiden yhdistäminen pakottaisi väärän tietomallin ainakin kahteen niistä. Päätös siitä, minkä tuoteperheen tarvitset, on ensimmäinen suunnitteluvalinta, ja se ratkeaa yleensä heti, kun tiedät, mitä vastaanottava järjestelmä toisella puolella todellisuudessa käyttää
Mitä eroa on FDF-, XFDF- ja XFA-lomaketiedoilla?
FDF ja XFDF kuljettavat samat tiedot kahdessa eri syntaksissa, ja XFA on aivan oma maailmansa. FDF on PDF-syntaksin mukainen pienoisasiakirja (ISO 32000-2 §12.7.8): /Fields-taulukko, joka koostuu << /T (nimi) /V (arvo) >> -sanakirjoista, joissa merkkijonot on suojattu (escape) täsmälleen samalla tavalla kuin merkkijonoliteraalit PDF-tiedoston sisällä. XFDF on saman tiedon XML-muoto (ISO 19444), <fields>-puu, jota Acrobat ja useimmat lomakkeen taustajärjestelmät lukevat ja kirjoittavat natiivisti. XFA ei ole kumpaakaan: se on XML Forms Architecture -malli ja sen tiedot, jotka on tallennettu XML Data Package (XDP) -muodossa, johon PDF viittaa polusta /AcroForm/XFA. Valitse FDF tai XFDF, when vaihdat kenttien arvoja muiden järjestelmien kanssa, ja turvaudu XFA:han vain silloin, kun ylläpidät asiakirjaa, joka on alun perin luotu XFA-lomakkeeksi
FDF:n ja XFDF:n sisällä losLab PDF Library vetää toisen rajan: kenttien arvot vastaan huomautuskommentit. Lomaketietoperhe (ExportFormDataToFDF, ImportFormDataFromFDF, ExportFormDataToXFDF, ImportFormDataFromXFDF) lukee ja kirjoittaa /Fields-alipuuta eikä koske mihinkään muuhun. Huomautusperhe (ExportAnnotationsToFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF, ImportAnnotationsFromXFDF) lukee ja kirjoittaa sen sijaan /Annots-alipuuta, jota Acrobat kutsuu nimellä 'Vie kommentit' (Export Comments). Nämä kaksi eivät koskaan mene päällekkäin, joten kenttien arvojen vieminen ei kerää mukaan irrallisia tarkistusmerkintöjä, eikä kommenttien tuominen häiritse arvoja, jotka käyttäjä on jo kirjoittanut. Se, mitä ohjausobjekti tekee, kun sitä napsautetaan tai se lasketaan uudelleen, on puolestaan kolmas asia, jota käsitellään oheisessa muistiinpanossa vuorovaikutteisista lomaketoiminnoista ja JavaScriptistä
Miten PDF-lomake täytetään FDF- tai XFDF-tiedostosta Delphissä?
Lataa asiakirja, kutsu yhtä tuontimenetelmää ja tallenna. ImportFormDataFromXFDF ja ImportFormDataFromFDF kukin jäsentävät saapuvan lomaketiedon, täsmäävät jokaisen merkinnän AcroForm-kenttään sen täysin määritellyn nimen (fully qualified name) perusteella, asettavat arvon ja palauttavat todellisuudessa päivitettyjen kenttien määrän. Molemmat menetelmät päivittävät vain kohde-PDF-tiedostossa jo olevia kenttiä; kumpikaan ei luo kenttää nimelle, jota lomake ei määrittele, mikä estää vierasta tai haitallista tietotiedostoa kasvattamasta lomakettasi salaa
var
Lib: TPDFlib;
FieldsSet: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.LoadFromFile('application-blank.pdf', '');
// Asianhallintajärjestelmän tuottama XFDF, valmiiksi UTF-8-muodossa levyllä
FieldsSet := Lib.ImportFormDataFromXFDF('applicant-1042.xfdf');
if FieldsSet > 0 then
Lib.SaveToFile('application-filled.pdf');
finally
Lib.Free;
end;
end;
Kaksi yksityiskohtaa ratkaisee, selviääkö monimutkaisempi tieto matkasta. Ensimmäinen on suojaus (escaping): FDF tallentaa arvot PDF-merkkijonoliteraaleina, joten arvo, joka sisältää sulkumerkin, kenoviivan tai tulostumattoman tavun, saapuu käärittynä standardin ISO 32000-2 §7.3.4.2 mukaiseen oktaalisuojaukseen, ja losLab PDF Library purkaa tämän suojauksen tuotaessa, jotta sulut ja vinoviivat palautuvat literaalimerkeiksi, jotka käyttäjä kirjoitti. Toinen on koodaus: tiedostopohjaiset menetelmät kirjoittavat ja lukevat XFDF- ja FDF-tiedostoja UTF-8-muodossa, mitä XFDF-määrittely edellyttää ja mitä kaikki muut kuin ASCII-kenttäarvot (esim. painotetut merkit, valuuttasymbolit, CJK-osoitteet) tarvitsevat säilyäkseen muuttumattomina. Jos rakennat XFDF:n itse, määritä UTF-8 ja kirjoita UTF-8, jolloin tuonti toimii oikein
Hierarkkiset kentät, monivalinnat ja rikas teksti
Hierarkkiset kenttien nimet ovat ensimmäinen paikka, jossa yksinkertainen viejä rikkoutuu. AcroForm osoittaa sisäkkäistä kenttää pistevälitteisellä koko nimellä, kuten Applicant.FullName, mutta XFDF ei laita tätä pistemerkein eroteltua merkkijonoa yhteen nimen määritteeseen (name attribute); standardi ISO 19444 asettaa sen sisäkkäin, muodossa <field name="Applicant"><field name="FullName">. losLab PDF Library jakaa pistenimen sisäkkäisiksi <field>-elementeiksi vietäessä ja kokoaa ne takaisin koko nimeksi tuotaessa, jotta molemmat suunnat pysyvät symmetrisinä. Vietäessä se myös ohittaa ei-terminaaliset isäntäkentät, koska AcroFormin isäntäsolmu edustaa vain nimeämistasoa eikä sillä ole omaa arvoa; sen vieminen tuottaisi tyhjän <value></value>-elementin, joka ei vastaa todellista lomaketta. Monivalintaiset luetteloruudut ovat toinen sudenkuoppa: valintakenttä voi sisältää useita valittuja arvoja samanaikaisesti, minkä XFDF ilmaisee toistuvina <value>-elementteinä ja FDF /V-taulukkona, ja losLab PDF Library jakaa kentän useiksi arvoiksi vain silloin, kun kyseessä on aidosti monivalintainen kenttä, jotta tavallinen monirivinen tekstikenttä säilyttää rivinvaihtonsa eikä hajoa virheellisiksi arvoiksi
Rikas teksti (rich text) on kolmas ja se, minkä kehittäjät tekevät useimmiten väärin. Muotoiltu kenttä tallentaa merkintänsä RV-merkintään XHTML-alipuuna, ja XFDF kuljettaa sen elementissä <value-richtext>. losLab PDF Library kirjoittaa tämän alipuun elävänä XML-fragmenttina sen sijaan, että se suojaisi sen merkkijonoksi, jotta jatkotyökalu lukee todellista rikasta tekstiä eikä näkyviä tageja; tuotaessa se säilyttää raa'an RV-alipuun ja soveltaa silti pelkkää tekstiä sisältävän <value>-arvon kenttään V. Jos kenttä tarjoaa molemmat, pelkkä arvo menee kenttään V ja rikas teksti kulkee mukana kohdassa RV, mikä on se yhteensopivuussääntö, joka estää rikkaan tekstin tuontia ylikirjoittamasta hiljaisesti toisen työkalun jo asettamaa arvoa. Kun rikas teksti on olemassa välittämään asiakirjan rakennetta avustavalle teknologialle, käsittele sitä samalla tavalla kuin lukujärjestystä, jota käsitellään muistiinpanossa sivutetuista PDF-tiedostoista ja saavutettavuusrakenteesta
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 kootaan uudelleen; Skills täyttää /V- ja /I-taulukot;
// Notes saa V-arvon <value>-elementistä ja RV-arvon <value-richtext>-elementistä
Lib.ImportFormDataFromXFDFString(XFDF);
Lib.SaveToFile('intake-filled.pdf');
finally
Lib.Free;
end;
end;
Miten huomautuskommentit siirretään edestakaisin FDF- tai XFDF-muodossa?
Kommentit siirtyvät huomautustuoteperheen kautta, ja tuettu osajoukko on tarkoituksella pieni. ExportAnnotationsToXFDF ja ImportAnnotationsFromXFDF sekä niiden FDF-vastineet kuljettavat tekstityylisiä merkintöjä kentillä, jotka siirtyvät puhtaasti edestakaisin: huomautuksen alityyppi (subtype), sen suorakulmio (rectangle), sen 0-perusteinen sivun indeksi, kirjoittaja kentässä T, aihe kentässä Subj, pelkkä sisältö Contents ja väri, joka mäppää PDF:n /C DeviceRGB-kolmikon XFDF-attribuutiksi #RRGGBB ja päinvastoin. Tuonti hyväksyy vain tunnetut elementtien nimet ja ohittaa kaikki merkinnät, joiden sivu on alueen ulkopuolella tai joiden suorakulmio puuttuu, jotta käsin muokattu tai vieras XFDF ei voi pudottaa virheellistä huomautusta asiakirjaan. Se, mitä osajoukko ei vielä kuljeta, on syytä sanoa suoraan: rikkaan tekstin sisältö (RC), ponnahdusikkunat (popups), quadpoint-pisteet, musteviivat (ink lists), kärkipisteet (vertices) ja valmiiksi piirretyt ulkoasuvirrat (appearance streams) ovat toistaiseksi soveltamisalan ulkopuolella, joten korostusgeometria ja mukautetut leimat eivät säily tällä polulla. Vahvistaaksesi sen, mikä todella päätyi perille, käy läpi sivun huomautukset tai laajempi elementtipuu, jota käsitellään artikkelissa tekstihaku ja sivuelementtien luettelointi
var
Src, Dest: TPDFlib;
Xfdf: WideString;
begin
Src := TPDFlib.Create;
Dest := TPDFlib.Create;
try
Src.LoadFromFile('reviewed.pdf', '');
Xfdf := Src.ExportAnnotationsToXFDFString; // Vain <annots>-osajoukko
Dest.LoadFromFile('clean-copy.pdf', ''); // sivujen on täsmättävä indeksin mukaan
Dest.ImportAnnotationsFromXFDFString(Xfdf);
Dest.SaveToFile('clean-copy-commented.pdf');
finally
Dest.Free;
Src.Free;
end;
end;
Kokonaisen XFA XDP -paketin kirjoittaminen SetXFAFromString-funktiolla
XFA on poikkeustapaus, ja SetXFAFromString on tapa, jolla kirjoitat koko paketin kerralla. Menetelmä ottaa vastaan täydellisen XML Data Package -paketin eli <xdp:xdp>-asiakirjan sen malli- ja tietojoukkopaketteineen, ja tallentaa sen virraksi, johon viitataan polusta /AcroForm/XFA. losLab PDF Library luo AcroForm-säiliön tarvittaessa, kun asiakirjalla ei ole sellaista, joten sinun ei tarvitse lisätä tarpeetonta kenttää vain antaaksesi XFA:lle kiinnityskohdan, ja se hävittää kaiken tallentamansa jäsennellyn XFA-tilan, jotta myöhempi luku heijastaa juuri kirjoittamaasi pakettia vanhentuneen välimuistin sijaan. Koska XFA-paketti on XML:ää eikä välttämättä UTF-8-muodossa, kirjasto tunnistaa UTF-16-tavujärjestysmerkin (BOM) ja purkaa paketin oikein ennen jäsentämistä, mikä on tärkeää työkaluilla tuotetuille paketeille, jotka käyttävät oletuksena UTF-16-koodausta
Kun paketti on paikallaan, GetXFAFormFieldValue ja SetXFAFormFieldValue osoittavat yksittäisiä kenttiä niiden Scripting Object Model (SOM) -polun kautta. losLab PDF Library hyväksyy standardit SOM-juuret sekä paljaat suhteelliset polut, joten form1.FullName, $data.form1.FullName ja xfa.datasets.data.form1.FullName viittaavat kaikki samaan tietosolmuun, ja mallipuoli hyväksyy $template- ja xfa.template-polut samalla tavalla. Tämä joustavuus on tärkeää silloin, kun toinen järjestelmä luo SOM-polut ja tuottaa aina täysin määritellyn muodon
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); // luo AcroForm-säiliön, jos sellaista ei ole olemassa
// lue takaisin data-DOM:in läpi SOM-polun avulla
if Lib.GetXFAFormFieldValue('form1.FullName') = 'Alice Example' then
Lib.SetXFAFormFieldValue('form1.FullName', 'Bob Example');
Lib.SaveToFile('xfa-packet.pdf');
finally
Lib.Free;
end;
end;
Rehellinen yhteenveto on, että kenttien arvot siirtyvät täysin edestakaisin FDF:n ja XFDF:n kautta, mukaan lukien hierarkia, monivalinnat ja rikas teksti; huomautuskommentit siirtyvät edestakaisin rajattuna tekstimerkintöjen osajoukkona selvin puuttein; ja XFA kirjoitetaan ja luetaan kokonaisena pakettina, jonka päällä on kenttäkohtainen SOM-pääsy. Sovita muoto vastaanottimeen, määritä UTF-8 kaikelle itse rakentamallesi ja muista, että tuontimenetelmät koskevat vain sellaisia kenttiä ja huomautuksia, jotka jo sopivat asiakirjaan. Tässä kuvatut lomaketieto-, huomautus- ja XFA-menetelmät ovat osa Delphille ja C++Builderille suunnattua losLab PDF Library -kirjastoa, jonka viiteopas sisältää täydellisen parametriluettelon jokaiselle vienti- ja tuontipisteelle