HotPDF exportiert und importiert PDF-Annotationen als XFDF über zwei Funktionen, die auf dem aktuell geladenen Dokument arbeiten, ExportLoadedAnnotationsToXFDF und ImportLoadedAnnotationsFromXFDF. XFDF ist das als ISO 19444-1 standardisierte XML-Austauschformat für Annotationen, und dieses Paar erlaubt es einem Delphi- oder C++Builder-Programm, seine Kommentare an Acrobat oder ein Review-Werkzeug eines Drittanbieters zu übergeben und die markierten Ergebnisse zurückzunehmen, alles ohne den Seiteninhalt neu zu schreiben, auf dem die Annotationen sitzen
Stellen Sie sich die beiden Richtungen vor, die das löst. Ein Reviewer öffnet Ihren generierten Bericht in Acrobat, setzt einen roten Pfeil auf eine verrutschte Abbildung, kreist eine falsche Summe ein und tippt eine Notiz an den Rand, dann exportiert er die Kommentare in eine kleine XFDF-Datei. Oder umgekehrt: Ihr Programm erzeugt die Markierungen selbst, und Sie müssen sie an jemanden liefern, dessen Werkzeug nicht HotPDF ist. In beiden Fällen reisen die Annotationen als XML, das beide Seiten verstehen, und die PDF-Seiten bleiben Byte für Byte, was sie waren
Was ist der Unterschied zwischen FDF und XFDF?
FDF und XFDF transportieren dieselbe Nutzlast in zwei verschiedenen Syntaxen, und der Unterschied zählt in dem Moment, in dem Sie entscheiden, welche Datei Sie einem anderen Werkzeug übergeben. FDF ist das ältere Forms Data Format, das innerhalb der PDF-Spezifikation selbst definiert ist: Es verwendet PDF-Objektsyntax, sodass eine FDF-Datei wie ein abgespecktes PDF aussieht und einen PDF-fähigen Parser zum Lesen braucht. XFDF ist der XML-Ausdruck derselben Daten, eigenständig als ISO 19444-1 standardisiert, was bedeutet, dass jede XML-Bibliothek auf jeder Plattform sie öffnen, vergleichen oder erzeugen kann. Beide Formate können Formularfeldwerte in einem <fields>-Baum transportieren, den ISO 19444-1 Abschnitt 6.3 regelt, und Annotationen in einem <annots>-Baum; HotPDF trennt diese Zuständigkeiten, leitet Formulardaten über ExportLoadedFormToXFDF und reserviert ExportLoadedAnnotationsToXFDF für die <annots>-Seite. Wenn Sie Kommentare mit einem Webservice, einem Java-Review-Server oder einem Skript austauschen, ist XFDF das Format, das die Gegenseite nicht zwingt, einen PDF-Parser einzubetten
Wie exportieren Sie PDF-Annotationen in Delphi als XFDF?
HotPDF exportiert Annotationen, indem es jede Seite des geladenen Dokuments durchläuft, für jede unterstützte Annotation ein XFDF-Element ausgibt und die Anzahl der geschriebenen Annotationen zurückgibt. Laden Sie zuerst das PDF, dann rufen Sie ExportLoadedAnnotationsToXFDF mit einem Zielpfad auf. Das Integer-Ergebnis ist die Zahl der serialisierten Annotationen; ein Ergebnis von null oder darunter bedeutet, dass nichts exportiert und keine Datei geschrieben wurde, was Ihr Signal ist, dass das Dokument keine Annotationen eines unterstützten Subtyps enthielt
var
Pdf: THotPDF;
Written: Integer;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('report-reviewed.pdf', '') > 0 then
begin
// Ein XFDF-Element je unterstützter Annotation auf jeder Seite schreiben
Written := Pdf.ExportLoadedAnnotationsToXFDF('comments.xfdf');
if Written <= 0 then
ShowMessage('No supported annotations were found');
end;
finally
Pdf.Free;
end;
end;
Das XFDF, das herauskommt, ist schlichtes, lesbares XML. HotPDF schreibt eine <xfdf>-Wurzel im ISO-19444-1-Namensraum, einen <annots>-Container und ein Kind je Annotation mit ihrem nullbasierten Seitenindex, ihrer Farbe und Geometrie als Attribute oder Kindelemente. Eine Linie mit gelber Füllung und offener Pfeilspitze, neben einem gefüllten Polygon, wird so serialisiert
<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/">
<annots>
<line page="0" start="72,700" end="220,700"
color="#FF0000" interior-color="#FFFF00"
head="OpenArrow" tail="None">
<contents-richtext>Baseline looks off</contents-richtext>
</line>
<polygon page="0" color="#0000FF" interior-color="#CCE5FF">
<vertices>72,120;180,120;180,200;72,200</vertices>
</polygon>
</annots>
</xfdf>
Wie Annotations-Subtypen auf XFDF-Elemente abgebildet werden
Jeder Annotations-Subtyp wird auf ein bestimmtes ISO-19444-1-Element mit eigener Geometriekonvention abgebildet, und HotPDF folgt diesen Strukturen, statt eigene zu erfinden. Linienannotationen tragen ein start- und ein end-Attribut mit den beiden Endpunkt-Koordinatenpaaren, direkt aus dem L-Array der Annotation übernommen, während die LE-Linienendstile zu head- und tail-Attributen werden. Polygon- und Polylinienannotationen verschieben ihre Punktliste in ein <vertices>-Kindelement als durch Semikolon getrennte x,y-Paare, nicht in ein Attribut, weil ein Leser, der das Kindelement erwartet, an anderer Stelle versteckte Punkte stillschweigend verwirft. Ink-Annotationen, die mehrere getrennte Striche enthalten können, verschachteln ein <inklist>-Element mit einem <gesture>-Kind je Strich, sodass eine mehrstrichige Unterschrift die Reise als getrennte Gesten übersteht statt als ein verschmolzener Klumpen
Rich Text, Farbe und Rahmenstil überleben neben der Geometrie. Der Rich-Text-Körper einer Notiz wird als <contents-richtext>-Kind geschrieben; die Innenfüllung, die PDF im IC-Array speichert, die Farbe innerhalb eines Kreises, Quadrats, Polygons oder einer Linienpfeilspitze sowie die Füllung eines Schwärzungskastens, kommt als interior-color-Attribut in der Form #RRGGBB an; und Rahmenbreite, Strichmuster und ein wolkiger Rahmeneffekt werden auf die Attribute width, dashes, style und intensity abgebildet, sodass ein wolkenumrandeter Callout am anderen Ende noch als wolkig gelesen wird. HotPDF bewahrt auch das an eine Markup-Annotation angehängte Popup-Fenster, importiert die Geometrie des Popup-Kindes und seinen geöffneten oder geschlossenen Zustand in das Popup-Dictionary der Annotation, und es überträgt die Öffnungs- und Review-Zustände von Textannotationen, sodass ein geprüftes Dokument nicht nur seine Formen behält, sondern auch die Workflow-Metadaten, auf die Reviewer sich verlassen
XFDF zurück in ein geladenes Dokument importieren
HotPDF importiert XFDF, indem es das XML parst, für jedes Element über NewLoadedAnnotation eine neue Annotation anlegt, sie an die vom Element benannte Seite hängt und zurückgibt, wie viele Annotationen hinzugefügt wurden. Der Workflow ist symmetrisch zum Export: Laden Sie das Basis-PDF, rufen Sie ImportLoadedAnnotationsFromXFDF mit der Datei des Reviewers auf und speichern Sie dann das geladene Dokument, um die neuen Markierungen zu persistieren. Fehlt die Datei oder lässt sich das XML nicht parsen, gibt die Funktion null zurück und das geladene Dokument bleibt unangetastet
var
Pdf: THotPDF;
Added: Integer;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('report.pdf', '') > 0 then
begin
Added := Pdf.ImportLoadedAnnotationsFromXFDF('comments.xfdf');
if Added > 0 then
Pdf.SaveLoadedDocument('report-annotated.pdf');
end;
finally
Pdf.Free;
end;
end;
Weil jedes XFDF-Element seinen eigenen Seitenindex benennt, landen Annotationen auf den Seiten, gegen die sie verfasst wurden, selbst wenn Sie mehrere Dateien nacheinander importieren, was es sicher macht, Kommentare von mehr als einem Reviewer auf demselben geladenen Dokument zu sammeln, bevor ein einziges Speichern erfolgt. Das folgende Beispiel führt zwei Reviewer in einer zusammengeführten Kopie zusammen. Wie Sie die Annotationsobjekte selbst im Code aufbauen und bearbeiten, statt sie als Dateien auszutauschen, zeigt, wie HotPDF PDF-Annotationsobjekte direkt aus Delphi erstellt und bearbeitet
var
Pdf: THotPDF;
Total, I: Integer;
Files: array[0..1] of string;
begin
Files[0] := 'alice-comments.xfdf';
Files[1] := 'bob-comments.xfdf';
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('master.pdf', '') > 0 then
begin
Total := 0;
for I := Low(Files) to High(Files) do
Inc(Total, Pdf.ImportLoadedAnnotationsFromXFDF(Files[I]));
if Total > 0 then
Pdf.SaveLoadedDocument('master-merged.pdf');
end;
finally
Pdf.Free;
end;
end;
Was sauber den Roundtrip übersteht und was nicht
HotPDF überträgt die Annotations-Subtypen im Roundtrip, denen ISO 19444-1 ein Zuhause gibt, und überspringt den Rest bewusst, statt etwas auszugeben, das ein Leser fehlinterpretieren würde. Die unterstützte Menge umfasst die Markup-Typen, die reale Review-Arbeit dominieren: Textnotizen, Freitext, Linie, Quadrat, Kreis, Polygon, Polylinie, die vier Text-Markup-Typen (Hervorhebung, Unterstreichung, Durchstreichung und Wellenlinie), Stempel, Ink und Caret, dazu Dateianhang, Ton, Schwärzung und Link, insgesamt achtzehn Subtypen. Eine Annotation, deren Subtyp außerhalb dieser Liste liegt, wird beim Export übergangen, und weil sie übersprungen statt leer geschrieben wird, bläht sie die von der Funktion zurückgegebene Zahl nicht auf
Rich Text ist der ehrliche Vorbehalt. HotPDF bewahrt den <contents-richtext>-Körper, sodass der formatierte Text und der reine Inhalt die Reise antreten, aber XFDF transportiert den Text und das Stil-Markup eines Kommentars, keinen gerenderten Appearance-Stream, sodass die empfangende Anwendung das Popup mit ihren eigenen Schriftarten und ihrem eigenen Layout neu zeichnet, statt die exakten Pixel von HotPDF zu reproduzieren. Behandeln Sie den Roundtrip als treu gegenüber Inhalt und Absicht, nicht gegenüber der Bildschirmdarstellung bis aufs Pixel. Wenn Ihr formatierter Inhalt in XFA-Formulardaten statt in Annotations-Streams lebt, gelten andere Regeln, und wie HotPDF XFA exData, Rich Text und Hyperlinks behandelt deckt diesen separaten Pfad ab
Die Behandlung auf Zeichenebene ist strenger, als sie aussieht, und genau das wollen Sie. HotPDF wendet beim Schreiben von Text die Escaping-Regeln aus ISO 19444-1 Abschnitt 5.8.2 an, kodiert die XML-relevanten Zeichen und Steuerbytes, sodass ein Kommentar mit einem Kaufmanns-Und, einer spitzen Klammer oder einem Zeilenumbruch wohlgeformtes XML ergibt, das jeder konforme Parser akzeptiert, und kehrt dieselben Regeln beim Import um. Deshalb kommt eine aus einer Tabellenkalkulation eingefügte Notiz samt aller Satzzeichen unversehrt zurück, statt die Datei zu beschädigen
Der Annotationsaustausch ist ein Ausschnitt dessen, was die API für geladene Dokumente leistet, und er lässt sich mit dem Rest kombinieren: Importieren Sie das XFDF eines Reviewers, passen Sie die Seiten an oder bearbeiten Sie die Dokumentmetadaten, glätten Sie die Datei oder vergeben Sie neue Berechtigungen und exportieren Sie dann ein frisches XFDF für die nächste Runde. All das wird in der Standard-HotPDF Delphi Component für Delphi und C++Builder ausgeliefert, deren Referenz die vollständige Abdeckung der Annotations-Subtypen und die begleitenden XFDF-Funktionen für Formulardaten dokumentiert