losLab PDF Library flytter formulardata ind og ud af en PDF på tre forskellige måder: FDF og XFDF til AcroForm-feltværdier, de samme to formater til annotationskommentarer og en hel XFA XDP-pakke skrevet direkte ind i formularen. ExportFormDataToXFDF, ImportFormDataFromXFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF og SetXFAFromString er indgangspunkterne, og hver af dem har en filvariant og en strengvariant
Årsagen til, at der er så mange metoder, er, at PDF-formulardata ikke er én enkelt ting. En udfyldt AcroForm har feltværdier, den kan også bære anmeldelseskommentarer, og en ældre XFA-formular indlejrer en hel XML-applikationsbeskrivelse, som ikke har noget med nogen af delene at gøre. losLab PDF Library holder bevidst disse tre bekymringer på separate API'er, fordi en sammenlægning af dem ville tvinge den forkerte datamodel ned over mindst to af them. At beslutte, hvilken familie du har brug for, er det første designvalg, og det afgøres normalt i det øjeblik, du ved, hvad det modtagende system på den anden side rent faktisk forbruger
Hvad er forskellen på FDF-, XFDF- og XFA-formulardata?
FDF og XFDF bærer de samme oplysninger i to forskellige syntakser, og XFA er en verden for sig. FDF is et miniaturedokument i PDF-syntaks (ISO 32000-2 §12.7.8): Et /Fields-array af << /T (navn) /V (værdi) >>-ordbøger, hvor strenge er undsluppet nøjagtigt som literale strenge undslipper inde i en PDF. XFDF er XML-formen af de samme data (ISO 19444), et <fields>-træ, som Acrobat og de fleste formular-backends læser og skriver indfødt. XFA er ingen af delene: Det er en XML Forms Architecture-skabelon plus dens data, gemt som en XML Data Package (XDP), som PDF'en refererer til fra /AcroForm/XFA. Vælg FDF eller XFDF, når du samarbejder om feltværdier, og ræk kun ud efter XFA, når du vedligeholder et dokument, der oprindeligt blev oprettet som en XFA-formular
Inden for FDF og XFDF trækker losLab PDF Library en anden linje: Feltværdier versus annotationskommentarer. Formular-data-familien (ExportFormDataToFDF, ImportFormDataFromFDF, ExportFormDataToXFDF, ImportFormDataFromXFDF) læser og skriver /Fields-undertræet og rører ikke andet. Annotationsfamilien (ExportAnnotationsToFDF, ImportAnnotationsFromFDF, ExportAnnotationsToXFDF, ImportAnnotationsFromXFDF) læser og skriver i stedet /Annots-undertræet, hvilket er det, Acrobat mener med Eksporter kommentarer. De to overlapper aldrig, så eksport af feltværdier vil ikke opsamle herreløse anmeldelsesnotater, og import af kommentarer vil ikke forstyrre de værdier, en bruger allerede har indtastet. Hada en widget gør, når der klikkes på den eller den genberegnes, er en helt tredje bekymring, der er dækket i den ledsagende note om interaktive formularhandlinger og JavaScript
Hvordan udfylder du en PDF-formular fra FDF eller XFDF in Delphi?
Indlæs dokumentet, kald én importmetode, og gem. ImportFormDataFromXFDF og ImportFormDataFromFDF fortolker hver især de indkommende formulardata, matcher hver post med et AcroForm-felt ud fra dets fuldt kvalificerede navn, indstiller værdien og returnerer antallet af felter, der faktisk er opdateret. Begge metoder opdaterer kun felter, der allerede eksisterer i mål-PDF'en; ingen af dem opfinder et felt til et navn, som formularen ikke definerer, hvilket forhindrer en vildfaren eller fjendtlig datafil i lydløst at udvide din formular
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;
To detaljer afgør, om ikke-trivielle data overlever rejsen. Den første er escaping: FDF gemmer værdier som PDF-literale strenge, så en værdi, der indeholder en parentes, en backslash eller en ikke-printbar byte, ankommer indpakket i den oktale escaping defineret i ISO 32000-2 §7.3.4.2, og losLab PDF Library vender denne escaping om ved import, så parenteser og skråstreger kommer tilbage som de bogstavelige tegn, brugeren indtastede. Den anden er kodning: De filbaserede metoder skriver og læser XFDF og FDF som UTF-8, hvilket er det, XFDF-erklæringen lover, og hvad enhver ikke-ASCII feltværdi (et navn med accent, et valutasymbol, en CJK-adresse) har brug for for at køre frem og tilbage uden korruption. Hvis du selv bygger XFDF'en, skal du erklære UTF-8 og skrive UTF-8, og importen vil være enig med dig
Hierarkiske felter, valg med flere værdier og formateret tekst
Hierarkiske feltnavne er det første sted, en naiv eksporter fejler. AcroForm adresserer et indlejret felt med en prikket fuld titel som f.eks. Applicant.FullName, men XFDF placerer ikke denne prikkede streng i en enkelt navneattribut; ISO 19444 indlejrer den som <field name="Applicant"><field name="FullName">. losLab PDF Library opdeler den prikkede titel i indlejrede <field>-elementer ved eksport og samler de indlejrede elementer igen til den fulde titel ved import, så de to retninger forbliver symmetriske. Ved eksport springer den også ikke-terminale forældrefelter over, fordi en forældrenode i en AcroForm kun bærer navngivningsniveauet og ikke har nogen værdi i sig selv; at udsende den ville producere en tom <value></value>, som ikke matcher den reelle formular. Liste-bokse med flere valg er den anden fælde: Et valgfelt kan indeholde flere valgte værdier på én gang, hvilket XFDF udtrykker som gentagne <value>-elementer og FDF udtrykker som et /V-array, og losLab PDF Library opdeler kun et felt i flere værdier, når det reelt er et valg med flere valg, så et almindeligt tekstfelt på flere linjer beholder sine linjeskift i stedet for at splintre op i falske værdier
Formateret tekst er den tredje, og den, folk oftest tager fejl af. Et felt med formatering gemmer sin markup i RV-posten som et XHTML-undertræ, og XFDF bærer det i <value-richtext>. losLab PDF Library skriver dette undertræ som et live XML-fragment frem for at undslippe det, så et efterfølgende værktøj læser ægte formateret tekst i stedet for en streng af synlige tags; ved import bevarer det det rå RV-undertræ og anvender stadig den almindelige <value> på V. Hvor et felt tilbyder begge dele, vinder den almindelige værdi for V, og den formaterede tekst kører med i RV, hvilket er interoperabilitetsreglen, der forhindrer en import af formateret tekst i lydløst at omskrive en værdi, som et andet værktøj allerede har indstillet. Når din formaterede tekst findes for at formidle dokumentstruktur til hjælpemiddelteknologi, skal du behandle den på samme måde, som du ville behandle læserækkefølgen diskuteret i noten om tagget PDF og tilgængelighedsstruktur
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;
Hvordan kører du annotationskommentarer frem og tilbage som FDF eller XFDF?
Kommentarer rejser i annotationsfamilien, og den understøttede delmængde er bevidst lille. ExportAnnotationsToXFDF og ImportAnnotationsFromXFDF, sammen med deres FDF-modstykker, bærer tekst-stil-markup med de felter, der rent faktisk kører rent frem og tilbage: Annotationsundertype, dens rektangel, dens 0-baserede sideindeks, forfatteren i T, emnet i Subj, det almindelige Contents og farven, som kortlægger PDF'ens /C DeviceRGB-triple til og fra en XFDF-#RRGGBB-attribut. Import accepterer kun kendte elementnavne og springer enhver post over, hvis side er uden for rækkevidde, eller hvis rektangel mangler, så en manuelt redigeret eller fremmed XFDF ikke kan tabe en fejlbehæftet annotation ind i dokumentet. Hvad delmængden endnu ikke bærer, er værd at sige tydeligt: Formateret tekstindhold (RC), popups, quadpoints, blæk-lister, hjørnepunkter og bagte udseendestrømme er uden for rækkevidde for nu, så fremhævelsesgeometri og brugerdefinerede stempeludseender vil ikke overleve denne sti. For at bekræfte, hvad der reelt landede, kan du gennemgå sideannotationerne eller det bredere elementtræ dækket i tekstsøgning og numerering af sideelementer
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;
Skrivning af en hel XFA XDP-pakke med SetXFAFromString
XFA er afvigeren, og SetXFAFromString er måden, hvorpå du skriver det hele på én gang. Metoden tager en komplet XML Data Package, <xdp:xdp>-dokumentet med dets skabelon- og datasæt-pakker, og gemmer det som den strøm, der refereres til fra /AcroForm/XFA. losLab PDF Library opretter AcroForm-containeren efter behov, når dokumentet ikke har nogen, så du ikke behøver at tilføje et spildt felt blot for at give XFA'en noget at hænge i, og det kasserer enhver fortolket XFA-tilstand, det holdt på, så en senere læsning afspejler den pakke, du lige har skrevet, i stedet for en forældet cache. Fordi en XFA-pakke er XML og ikke nødvendigvis UTF-8, registrerer biblioteket et UTF-16 byte-order mark og afkoder pakken korrekt før fortolkning, hvilket har betydning for pakker produceret af værktøjer, der standardiserer til UTF-16
Når pakken er på plads, adresserer GetXFAFormFieldValue og SetXFAFormFieldValue individuelle felter via deres Scripting Object Model-sti. losLab PDF Library accepterer standard SOM-rødder samt rå relative stier, så form1.FullName, $data.form1.FullName og xfa.datasets.data.form1.FullName alle opløses to den samme datanode, og skabelonsiden accepterer $template og xfa.template på samme måde. Denne tolerance betyder noget, når SOM-stierne genereres af et andet system, der altid udsender den fuldt kvalificerede form
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;
Den ærlige opsummering er, at feltværdier kører fuldt frem og tilbage via FDF og XFDF, inklusive hierarki, flere valg og formateret tekst; annotationskommentarer kører frem og tilbage som en defineret delmængde af tekst-markup med klare mangler; og XFA skrives og læses som en hel pakke med SOM-adgang pr. felt oveni. Match formatet til forbrugeren, erklær UTF-8 for alt, hvad du bygger i hånden, og husk, at importmetoderne kun nogensinde rører ved felter og annotationer, der allerede passer til dokumentet. Metoderne til formular-data, annotation og XFA beskrevet her er en del af losLab PDF Library til Delphi og C++Builder, hvis reference indeholder den fulde parameterliste for ethvert indgangspunkt for eksport og import