losLab PDF Library flyttar formulärdata in och ut ur en PDF på tre olika sätt: FDF och XFDF för AcroForm-fältvärden, samma två format för anteckningskommentarer, och ett helt XFA XDP-paket skrivet direkt i formuläret. ExportFormDataToXFDF, ImportFormDataFromXFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF och SetXFAFromString är startpunkterna, och var och en av dem har en filvariant och en strängvariant
Anledningen till att det finns så många metoder är att PDF-formulärdata inte är en enda sak. Ett ifyllt AcroForm has fältvärden, det kan också innehålla granskningskommentarer, och ett äldre XFA-formulär bäddar in en hel XML-applikationsbeskrivning som inte har något att göra med något av detta. losLab PDF Library håller dessa tre delar i separata API:er med avsikt, eftersom en sammanslagning skulle tvinga på fel datamodell på minst två av dem. Att bestämma vilken familj du behöver är det första designvalet, och det avgörs vanligtvis så fort du vet vad det mottagande systemet på andra sidan faktiskt konsumerar
Vad är skillnaden mellan FDF-, XFDF- och XFA-formulärdata?
FDF och XFDF bär på samma information i två olika syntaxer, och XFA är en separat värld. FDF är ett dokument i miniatyr med PDF-syntax (ISO 32000-2 §12.7.8): en /Fields-matris med << /T (namn) /V (värde) >>-ordböcker, med strängar escaperade exakt på samma sätt som literala strängar escaperas inuti en PDF. XFDF is XML-formen av samma data (ISO 19444), ett <fields>-träd som Acrobat och de flesta formulärsystem läser och skriver inbyggt. XFA är inget av detta: det är en XML Forms Architecture-mall plus dess data, lagrad som ett XML Data Package (XDP) som PDF-filen refererar till från /AcroForm/XFA. Välj FDF eller XFDF när du samverkar med fältvärden, och sträck dig efter XFA endast när du underhåller ett dokument som ursprungligen skapades som ett XFA-formulär
Inom FDF och XFDF drar losLab PDF Library en andra linje: fältvärden kontra anteckningskommentarer. Formulärdatafamiljen (ExportFormDataToFDF, ImportFormDataFromFDF, ExportFormDataToXFDF, ImportFormDataFromXFDF) läser och skriver under-trädet /Fields och rör ingenting annat. Anteckningsfamiljen (ExportAnnotationsToFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF, ImportAnnotationsFromXFDF) läser och skriver istället under-trädet /Annots, vilket är vad Acrobat menar med Exportera kommentarer. De två överlappar aldrig, så export av fältvärden kommer inte att sopa upp herrelösa granskningsanteckningar, och import av kommentarer kommer inte att störa de värden som en användare redan har skrivit in. Vad en kontroll gör när den klickas eller beräknas om är en helt annan sak, som täcks i den tillhörande artikeln om interaktiva formuläråtgärder och JavaScript
Hur fyller man i ett PDF-formulär från FDF eller XFDF i Delphi?
Läs in dokumentet, anropa en importmetod och spara. ImportFormDataFromXFDF och ImportFormDataFromFDF analyserar vardera inkommande formulärdata, matchar varje post till ett AcroForm-fält med dess fullständiga namn, ställer in värdet och returnerar antalet fält som faktiskt uppdaterats. Båda metoderna uppdaterar endast fält som redan finns i mål-PDF-filen; ingen av dem skapar ett fält för ett namn som formuläret inte definierar, vilket förhindrar att en herrelös eller fientlig datafil tyst utökar ditt 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;
Två detaljer avgör om icke-trivial data överlever resan. Den första är escaping: FDF lagrar värden som literala PDF-strängar, så ett värde som innehåller en parentes, ett omvänt snedstreck eller en icke-utskrivbar byte anländer insvept i den oktala escaping som definieras i ISO 32000-2 §7.3.4.2, och losLab PDF Library vänder på denna escaping vid import så att parenteser och snedstreck kommer tillbaka som de tecken användaren skrev. Den andra är kodning: de filbaserade metoderna skriver och läser XFDF and FDF som UTF-8, vilket är vad XFDF-deklarationen lovar och vad alla fältvärden som inte är ASCII (ett namn med accenter, en valutasymbol, en CJK-adress) behöver för att kunna skickas fram och tillbaka utan korruption. Om du bygger XFDF själv, deklarera UTF-8 och skriv UTF-8, så kommer importen att stämma överens med dig
Hierarkiska fält, flerval och formaterad text
Hierarkiska fältnamn är det första stället där en naiv exporterare går sönder. AcroForm adresserar ett nästlat fält med en punktseparerad fullständig titel som Applicant.FullName, men XFDF placerar inte den punktseparerade strängen i ett enda namnattribut; ISO 19444 nästlar det, som <field name="Applicant"><field name="FullName">. losLab PDF Library delar upp den punktseparerade titeln i nästlade <field>-element vid export och sätter ihop de nästlade elementen till den fullständiga titeln vid import, så att de två riktningarna förblir symmetriska. Vid export hoppar den också över föräldrafält som inte är slutnoder, eftersom en föräldranod i ett AcroForm endast bär på namngivningsnivån och inte har något eget värde; att exporterar det skulle generera ett tomt <value></value> som inte matchar det verkliga formuläret. Flervalsrutor är den andra fällan: ett valfält kan innehålla flera valda värden samtidigt, vilket XFDF uttrycker som upprepade <value>-element och FDF uttrycker som en /V-matris, och losLab PDF Library delar endast upp ett fält i flera värden när det verkligen är ett flervalsfält, så att ett vanligt flerradigt textfält behåller sina radbrytningar istället för att splittras upp i felaktiga värden
Formaterad text (rich text) är det tredje, och det som folk oftast gör fel på. Ett fält med formatering lagrar sin markup i posten RV som ett XHTML-underträd, och XFDF bär med sig det i <value-richtext>. losLab PDF Library skriver detta underträd som ett live XML-fragment snarare än att escaperar det, så att ett efterföljande verktyg läser riktig formaterad text istället för en sträng av synliga taggar; vid import bevarar det det råa RV-underträdet och applicerar fortfarande den vanliga <value> på V. Där ett fält erbjuder båda vinner det vanliga värdet för V och den formaterade texten följer med i RV, vilket är den samverkansregel som hindrar en rich-text-import från att tyst skriva över ett värde som ett annat verktyg redan har angett. När din formaterade text finns för att förmedla dokumentstruktur till hjälpmedel, behandla den på samma sätt som du skulle behandla läsordningen som diskuteras i artikeln om taggad PDF och tillgänglighetsstruktur
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;
Hur skickar man anteckningskommentarer fram och tillbaka som FDF eller XFDF?
Kommentarer färdas på anteckningsfamiljen, och den delmängd som stöds är medvetet liten. ExportAnnotationsToXFDF och ImportAnnotationsFromXFDF, tillsammans med deras FDF-motsvarigheter, bär med sig markup i textstil med de fält som faktiskt skickas fram och tillbaka utan problem: anteckningsundertypen, dess rektangel, dess 0-baserade sidindex, författaren i T, ämnet i Subj, det vanliga Contents och färgen, som mappar PDF-filens /C DeviceRGB-trippel till och från ett XFDF-#RRGGBB-attribut. Importen accepterar endast kända elementnamn och hoppar över alla poster vars sida är utanför intervallet eller vars rektangel saknas, så att en manuellt redigerad eller utländsk XFDF inte kan släppa in en felaktig anteckning i dokumentet. Vad denna delmängd ännu inte bär med sig är värt att säga rent ut: formaterat textinnehåll (RC), popup-fönster, fyrhörningspunkter (quadpoints), bläcklistor, brytpunkter och bakade utseendeströmmar ligger utanför tillämpningsområdet för tillfället, så markeringsgeometri och anpassade stämpelutseenden kommer inte att överleva denna väg. För att bekräfta vad som faktiskt landade kan du gå igenom sidanteckningarna eller det bredare elementträdet som täcks i textsökning och sidselementsuppräkning
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;
Skriva ett fullständigt XFA XDP-paket med SetXFAFromString
XFA är avvikaren, och SetXFAFromString är hur du skriver hela saken på en gång. Metoden tar ett fullständigt XML Data Package, <xdp:xdp>-dokumentet med dess mall- och datamängdspaket, och lagrar det som strömmen som refereras från /AcroForm/XFA. losLab PDF Library skapar AcroForm-containern vid behov när dokumentet inte har någon, så du behöver inte lägga till ett tillfälligt fält bara för att ge XFA något ställe att hänga på, och det kastar bort alla analyserade XFA-tillstånd som det innehöll så att en senare läsning återspeglar det paket du just skrev snarare än en föråldrad cache. Eftersom ett XFA-paket är XML och inte nödvändigtvis UTF-8, upptäcker biblioteket en UTF-16-byteordningsmarkering (BOM) och avkodar paketet korrekt innan analys, vilket är viktigt för paket som produceras av verktyg som har UTF-16 som standard
När paketet väl är på plats adresserar GetXFAFormFieldValue och SetXFAFormFieldValue enskilda fält via deras Scripting Object Model-sökväg. losLab PDF Library accepterar SOM-standardrötter samt enkla relativa sökvägar, så form1.FullName, $data.form1.FullName och xfa.datasets.data.form1.FullName matchar alla samma datanod, och mallsidan accepterar $template och xfa.template på samma sätt. Den toleransen är viktig när SOM-sökvägarna genereras av ett annat system som alltid genererar det fullständiga namnet
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;
Var troheten slutar
Känn till gränserna innan du anförtror ett arbetsflöde till dessa bryggor. Datamängdsexporteraren hoppar över binära kolumner tyst, så en rapport som måste visa en inbäddad bild behöver ett annat tillvägagångssätt än en vanlig tabell. QuickReport-banan, eftersom den går via EMF, bakar in text i vektorfigurer — sidan ser rätt ut men innehåller ingen valbar eller sökbar text och ingen taggad PDF-struktur för tillgänglighetsstruktur. FastReport och ReportBuilder behåller riktig text, men de typade hanterarna täcker de vanliga vyerna — memo, bild, form, linje — och faller tillbaka på en begränningsruta eller hoppar över de exotiska, så en rapport som förlitar sig på rik text, streckkoder eller gradientfyllningar kommer att förlora detaljer. Inget av detta är en defekt; det är den ärliga gränsen för ett översättningslager
Ett driftsmässigt förbehåll går före resten. Ingen av de tre motorerna levereras inuti losLab PDF Library, och bryggorna är avsiktligt uteslutna från huvudbygget — de kompileras endast från ett projekt som redan har FastReport VCL 6.x, QuickReport 8 eller ReportBuilder 20 i sin sökväg. Metafil- och DrawCommand-ytorna de riktar in sig på har förblivit stabila under flera stora motorversioner, men du ansvarar för att versionerna matchar. Få det rätt och de två banorna täcker hela bredden, från en ad-hoc DBGrid-dump till en designad faktura. Tabellsexporteraren och rapportbryggorna levereras båda med losLab PDF Library för Delphi och C++Builder