Het PDFium Component voor Delphi en Lazarus wisselt formuliergegevens en annotaties uit via XFDF, het XML-uitwisselingsformaat gedefinieerd door ISO 19444-1. TPdf.ExportXFDF serialiseert elke formulierveldwaarde en elke ondersteunde annotatie in het geladen document naar een XFDF-bestand of TStream; TPdf.ImportXFDF leest een XFDF-document terug, waarbij annotaties opnieuw op hun pagina's worden aangemaakt en veldwaarden worden toegepast. Die ene heen-en-weerronde dekt twee workflows die elke documentapplicatie uiteindelijk nodig heeft: een revisor markeert een PDF in Acrobat en mailt u de opmerkingen om samen te voegen, of een nalevingsregel stelt dat formuliergegevens in een apart, diffbaar en controleerbaar bestand moeten staan in plaats van in de PDF zelf te worden ingebakken
Ondersteunt PDFium XFDF-import en -export?
De PDFium-bibliotheek zelf ondersteunt dit niet. De systeemeigen C-API heeft helemaal geen XFDF- of FDF-functies — niets in de openbare headers leest of schrijft een van beide formaten, dus geen enkele vorm van wrapping helpt u verder. Het PDFium Component implementeert de volledige XFDF-engine daarom in Pascal, in een speciale unit die de XML rechtstreeks opbouwt en ontleedt op basis van het bestaande data-model voor TPdf-annotaties en -formuliervelden. De schrijver genereert de XML handmatig en de lezer is een handgeschreven state-machine parser, waardoor de functie geen afhankelijkheid toevoegt van Delphi XMLDoc of de FPC DOM-units, en identiek gedrag vertoont in Delphi en Lazarus
Die ontwerpkeuze is belangrijk wanneer u alternatieven evalueert. Als u systeemeigen FPDF_*-functies vanuit Pascal hebt aangeroepen, is XFDF een barrière: de functionaliteit bevindt zich simpelweg niet in de DLL. Het component doorbreekt die barrière door XFDF te behandelen als een puur serialisatieprobleem — verzamel de veldwaarden en annotatierecords die de wrapper al kan lezen, schrijf ze uit als standaard XML en keer het proces om bij het importeren
Wat bevat een XFDF-bestand?
ISO 19444-1 definieert XFDF als de XML-weergave van FDF, en de payload is opgesplitst in twee topniveaublokken. Het <fields>-element bevat hiërarchische formulierveldnamen en hun waarden — alles wat een gebruiker in een AcroForm heeft getypt, gekozen of aangevinkt. Het <annots>-element bevat de annotaties: TPdf.ExportXFDF genereert 18 subtypen — tekst (text), markering (highlight), onderstreping (underline), doorstreping (strikeout), golvend (squiggly), lijn (line), cirkel (circle), vierkant (square), dakje (caret), polygoon (polygon), polylijn (polyline), stempel (stamp), inkt (ink), vrije tekst (freetext), bestandsbijlage (fileattachment), geluid (sound), link en redigeren (redact). Widget-annotaties ontbreken bewust in <annots> omdat hun gegevens meereizen in <fields>, en viewer-interne subtypen zoals Popup maken geen deel uit van de XFDF-vocabulaire
Om de heen-en-weerronde getrouw te maken, is het TPdfAnnotation-record uitgebreid met de metadata die XFDF verwacht: Name (de unieke identificator NM), Subject, ModificationDate, CreationDate, Icon, Opacity, lijneindpunten, polygoon- en polylijn-hoekpunten en inkt-gebarenpaden. Elk nieuw veld is gekoppeld aan een booleaanse sentinel Has*, zodat code die annotaties heeft opgebouwd tegen eerdere versies blijft compileren en dezelfde woordenboeken blijft produceren — een niet-ingesteld veld wordt nooit geschreven. Als u al programmatisch markeringen maakt, bevat hetzelfde record dat u gebruikt voor tekstmarkeringsannotaties met quad points nu alles wat XFDF nodig heeft
Hoe exporteert u formuliergegevens en annotaties naar XFDF?
Eén aanroep dekt het hele document. Laad de PDF met formulierinvulling ingeschakeld, roep ExportXFDF aan en de component doorloopt elke pagina, verzamelt veldwaarden en annotaties en schrijft de XML. De retourwaarde is het aantal geschreven UTF-8-bytes, wat een snelle controle in logboeken mogelijk maakt
var
Pdf: TPdf;
Bytes: Integer;
begin
Pdf := TPdf.Create(Self);
Pdf.FormFill := True; // nodig zodat de veldwaarden live zijn
Pdf.FileName := 'expense-report.pdf';
Pdf.Active := True;
Bytes := Pdf.ExportXFDF('expense-report.xfdf');
ShowMessage(Format('%d bytes aan XFDF geschreven', [Bytes]));
end;
Beide richtingen hebben een TStream-overload, dus er is geen tijdelijk bestand op de schijf vereist. Exporteren naar een TMemoryStream is de natuurlijke vorm wanneer de XFDF bestemd is voor een HTTP-respons, een database-blob of een ondertekende archiefinvoer
var
Buffer: TMemoryStream;
begin
Buffer := TMemoryStream.Create;
try
Pdf.ExportXFDF(Buffer); // dezelfde XML, geen bestand nodig
Buffer.Position := 0;
// geef de stream door aan een webrespons, blob-kolom of zip-invoer
finally
Buffer.Free;
end;
end;
Hoe voegt ImportXFDF opmerkingen weer samen in het document?
Aan de importzijde sluit de revisorworkflow. Een collega annoteert het contract in Acrobat, exporteert opmerkingen als XFDF en stuurt u een paar kilobytes aan XML in plaats van een tweede kopie van de PDF. TPdf.ImportXFDF ontleedt dat bestand, maakt elke annotatie aan op de pagina die door het attribuut page wordt genoemd en schrijft veldwaarden in de bijbehorende widget-annotaties. De functie retourneert het gecombineerde aantal toegepaste velden plus annotaties, zodat de UI exact kan bevestigen wat er is binnengekomen
var
Applied: Integer;
begin
Applied := Pdf.ImportXFDF('review-comments.xfdf');
StatusBar.SimpleText :=
Format('%d velden en annotaties samengevoegd', [Applied]);
end;
De parser is een handgeschreven tagscanner gebouwd op tolerantie in plaats van strengheid: onbekende elementen worden overgeslagen, verwerkingsinstructies, DOCTYPE-declaraties en opmerkingen worden genegeerd, onbekende vlaggen worden weggelaten en attribuutwaarden worden gedecodeerd via de volledige set van XML-entiteiten en numerieke karakterreferenties, inclusief UTF-16-surrogaatparen. XFDF geproduceerd door Acrobat, door een webviewer of door een ander hulpmiddel wordt probleemloos samengevoegd. Zodra de annotaties in het document staan, wordt de revisiecyclus voortgezet met het antwoord- en statusmechanisme dat is beschreven in het bouwen van een annotatierevisieworkflow met het PDFium Component, en geïmporteerde veldwaarden nemen deel aan de normale tabvolgordelogica die wordt behandeld in formulierveldnavigatie
Waarom zijn decimaalscheidingstekens belangrijk voor XFDF?
Elke annotatie in XFDF wordt gepositioneerd door coördinatenstrings — rect="70.5,540,200,560" en dergelijke — en ISO 19444-1 vereist de punt als decimaalscheidingsteken. De standaard Delphi-formatteringsmethode voor zwevendekommagetallen volgt de Windows-regio-instellingen, dus op een Duits of Frans systeem verandert een naïeve FloatToStr 70.5 in 70,5, wat een door komma's gescheiden coördinatenlijst verminkt tot onzin die andere verwerkers weigeren of verkeerd lezen. Het PDFium Component normaliseert elk getal dat het schrijft: het decimaalscheidingsteken van de regio-instelling wordt herschreven naar een punt en overtollige nullen aan het einde worden weggelaten, zodat het geëxporteerde bestand byte-identiek is of het nu op een en-US of een de-DE machine is gegenereerd. Als u ooit een PDF-tool hebt gedebugd die op kantoor werkte maar bij een Europese klant faalde, hebt u deze exacte klasse van bugs ontmoet — goed om te weten dat de component dit voor u regelt
Wat zijn de grenzen van de heen-en-weerronde?
Twee grenzen zijn de moeite waard om duidelijk te stellen. Ten eerste transporteert XFDF annotatiegegevens, en niet de gerenderde weergaven — weergavestromen (appearance streams) maken geen deel uit van het formaat, dus de ontvangende viewer genereert het uiterlijk van elke annotatie opnieuw op basis van haar eigenschappen. Een markering of vierkant zal overal correct renderen; een stempel met een aangepast uiterlijk zal terugvallen op wat de doelviewer voor die stempelnaam tekent. Ten tweede heeft de onderliggende PDFium-API setters voor strings, maar geen voor annotatienummers of padgeometrie, dus Opacity, lijneindpunten, hoekpunten en inkt-gebarenpaden zijn alleen voor export: de component behoudt ze getrouw bij het schrijven van XFDF, maar kan ze niet terugschrijven naar een PDF bij het importeren. Veldwaarden, inhoud, kleuren, rechthoeken (rects), quad points, data en metadata voor identiteit doorlopen de heen-en-weerronde in beide richtingen
Voor een snelle start wordt het XfdfLab-voorbeeld meegeleverd in de demosets voor Delphi, C++Builder en Lazarus, dat beide aanroepen koppelt aan knoppen over elke geopende PDF. XFDF-ondersteuning is inbegrepen in de huidige release van het PDFium Component, samen met de annotatie- en formulier-API's waarop het is gebouwd