Teknisk artikel

Importera och exportera PDF-anteckningar som XFDF i Delphi

HotPDF exporterar och importerar PDF-anteckningar som XFDF via två funktioner som verkar på det för närvarande laddade dokumentet, ExportLoadedAnnotationsToXFDF och ImportLoadedAnnotationsFromXFDF. XFDF är XML-anteckningsutbytesformatet standardiserat som ISO 19444-1, och detta par gör det möjligt för ett Delphi- eller C++Builder-program att skicka sina kommentarer till Acrobat eller ett tredjepartsgranskningsverktyg och ta tillbaka de markerade resultaten, allt utan att skriva om sidinnehållet som anteckningarna ligger på

Föreställ dig de två riktningarna detta löser. En granskare öppnar din genererade rapport i Acrobat, lägger till en röd pil på en feljusterad figur, ringar in en felaktig totalsumma och skriver en anteckning i marginalen och exporterar sedan kommentarerna till en liten XFDF-fil. Eller omvänt: ditt program producerar markeringarna självt och du behöver skicka dem till någon vars verktyg inte är HotPDF. Oavsett vilket färdas anteckningarna som XML som båda sidor förstår, och PDF-sidorna förblir exakt vad de var byte för byte

Vad är skillnaden mellan FDF och XFDF?

FDF och XFDF bär på samma innehåll i två olika syntaxer, och skillnaden spelar roll i samma ögonblick som du bestämmer dig för vilken fil du ska ge ett annat verktyg. FDF är det äldre Forms Data Format som definieras inuti själva PDF-specifikationen: det använder PDF-objektsyntax, så en FDF-fil ser ut som en avskalad PDF och behöver en PDF-medveten parser för att läsas. XFDF är XML-uttrycket för samma data, oberoende standardiserat som ISO 19444-1, vilket innebär att alla XML-bibliotek på vilken plattform som helst kan öppna, jämföra eller generera det. Båda formaten kan bära formulärfältvärden i ett <fields>-träd, vilket styrs av ISO 19444-1 klausul 6.3, och anteckningar i ett <annots>-träd; HotPDF delar upp dessa ansvarsområden, dirigerar formulärdata via ExportLoadedFormToXFDF och reserverar ExportLoadedAnnotationsToXFDF för <annots>-sidan. När du utbyter kommentarer med en webbtjänst, en Java-granskningsserver eller ett skript är XFDF formatet som inte tvingar den andra sidan att bädda in en PDF-parser

Hur exporterar du PDF-anteckningar som XFDF i Delphi?

HotPDF exporterar anteckningar genom att gå igenom varje sida i det laddade dokumentet, generera ett XFDF-element för varje anteckning som stöds och returnera antalet skrivna anteckningar. Ladda PDF-filen först och anropa sedan ExportLoadedAnnotationsToXFDF med en målsökväg. Det returnerade heltalet är antalet serialiserade anteckningar; ett resultat på noll eller mindre innebär att ingenting exporterades och ingen fil skrevs, vilket är din signal att dokumentet inte innehöll några anteckningar av en understödjartyp som stöds

var
  Pdf: THotPDF;
  Written: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('report-reviewed.pdf', '') > 0 then
    begin
      // Write one XFDF element per supported annotation on every page
      Written := Pdf.ExportLoadedAnnotationsToXFDF('comments.xfdf');
      if Written <= 0 then
        ShowMessage('No supported annotations were found');
    end;
  finally
    Pdf.Free;
  end;
end;

Den XFDF som kommer ut är vanlig, läsbar XML. HotPDF skriver en <xfdf>-rot i namnrymden för ISO 19444-1, en <annots>-container och ett barn per anteckning med dess nollbaserade sidindex, färg och geometri som attribut eller under-element. En linje med en gul fyllning och ett öppet pilhuvud, som ligger bredvid en fylld polygon, serialiseras så här

<?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>

Hur anteckningsundertyper mappar till XFDF-element

Varje anteckningsundertyp mappar till ett specifikt ISO 19444-1-element med sin egen geometri-konvention, och HotPDF följer dessa strukturer snarare än att uppfinna egna. Linje-anteckningar bär på ett start- och ett end-attribut som innehåller de två koordinatparen för ändpunkterna, tagna direkt från anteckningens L-matris, medan linjeavslutningsstilarna LE blir head- och tail-attribut. Polygon- och polylinje-anteckningar flyttar sin punktlista till ett under-element <vertices> som semikolonseparerade x,y-par, inte ett attribut, eftersom en läsare som förväntan sig under-elementet tyst kommer att kasta bort punkter gömda någon annanstans. Bläck-anteckningar (ink), som kan innehålla flera separata streck, nästlar ett <inklist>-element med ett under-element <gesture> per streck, så att en signatur med flera streck överlever resan som distinkta gester istället för en sammanfogad blob

Formaterad text, färg och kantlinjestil överlever tillsammans med geometrin. En antecknings rich-text-kropp skrivs som ett under-element <contents-richtext>; den inre fyllningen som PDF lagrar i IC-matrisen, färgen inuti en cirkel, kvadrat, polygon eller linjepilhuvud och fyllningen i en redigeringsruta, kommer över som ett interior-color-attribut i #RRGGBB-form; och kantbredd, streckat mönster och en molnig kanteffekt mappar till attributen width, dashes, style och intensity, så att en molnkonturerad bildtext fortfarande visas som molnig i den andra änden. HotPDF bevarar också popup-fönstret som är kopplat till en markeringsanteckning, och importerar popup-fönstrets geometri och dess öppna eller stängda tillstånd till anteckningens Popup-ordbok, och den bär med sig textanteckningens öppnings- och granskningsstatus, så att ett granskat dokument inte bara behåller sina former utan även de metadata för arbetsflöden som granskare förlitar sig på

Importera XFDF tillbaka till ett laddat dokument

HotPDF importerar XFDF genom att tolka XML-koden, skapa en ny anteckning för varje element via NewLoadedAnnotation, koppla den till sidan som elementet anger och returnera hur många anteckningar den lade till. Arbetsflödet är symmetriskt med exporten: ladda bas-PDF-filen, anropa ImportLoadedAnnotationsFromXFDF med granskarens fil och spara sedan det laddade dokumentet för att spara de nya markeringarna. Om filen saknas eller om XML-koden inte kan tolkas returnerar funktionen noll och det laddade dokumentet lämnas orört

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;

Eftersom varje XFDF-element anger sitt eget sidindex hamnar anteckningarna på de sidor de skapades mot, även när du importerar flera filer i rad, vilket gör det säkert att samla in kommentarer från mer än en granskare på samma laddade dokument innan du sparar en enda gång. Exemplet nedan slår ihop två granskares kommentarer till en sammanfogad kopia. För att bygga och redigera anteckningsobjekten själva i kod istället för att utbyta dem som filer, se hur HotPDF skapar och redigerar PDF-anteckningsobjekt direkt från Delphi

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;

Vad som överförs rent tur och retur, och vad som inte gör det

HotPDF överför de anteckningsundertyper som ISO 19444-1 ger ett hem, och hoppar medvetet över resten istället för att generera något som en läsare skulle tolka fel. Den uppsättning som stöds spänner över de markeringstyper som dominerar verkligt granskningsarbete: textanteckningar, fritext, linje, kvadrat, cirkel, polygon, polylinje, de fyra textmarkeringstyperna (markering, understrykning, genomstrykning och vågig understrykning), stämpel, bläck och insättningstecken, plus filbilaga, ljud, redigering och länk, totalt arton undertyper. En anteckning vars undertyp faller utanför den listan hoppas över vid export, och eftersom den hoppas över istället för att skrivas tom, blåser den inte upp antalet som funktionen returnerar

Formaterad text (rich text) är det ärliga förbehållet. HotPDF bevarar kroppen <contents-richtext> så att den formaterade texten och det vanliga innehållet följer med på resan, men XFDF bär på en kommentars text- och stilmarkering, inte en renderad utseendeström, så det mottagande programmet ritar om popup-fönstret med sina egna teckensnitt och layout istället för att återskapa HotPDF:s exakta pixlar. Behandla överföringen som trogen vad gäller innehåll och avsikt, inte till renderingen på skärmen ner till pixeln. Om ditt formaterade innehåll lever i XFA-formulärdata istället för anteckningsströmmar skiljer sig reglerna, och hur HotPDF hanterar XFA exData, formaterad text och hyperlänkar täcker den separata banan

Hanteringen på teckennivå är striktare än den ser ut, vilket är precis vad du vill ha. HotPDF tillämpar eskaperingsreglerna i ISO 19444-1 klausul 5.8.2 når det skriver text, och kodar XML-känsliga tecken och kontrollbyte så att en kommentar som innehåller ett och-tecken, en vinkelparentes eller en radbrytning ger välformad XML som alla kompatibla parser accepterar, och det vänder på samma regler vid import. Det är därför en anteckning som klistras in från ett kalkylblad, inklusive skiljetecken, kommer tillbaka intakt istället för att korrumpera filen

Utbyte av anteckningar är en del av vad API:et för laddade dokument gör, och det samverkar med resten: importera en granskares XFDF, justera sidorna eller redigera dokumentets metadata, platta till eller ändra behörigheter för filen och exportera sedan en ny XFDF för nästa omgång. Allt levereras i standardversionen av HotPDF Component för Delphi och C++Builder, vars referens dokumenterar den fullständiga täckningen av anteckningsundertyper och de tillhörande XFDF-funktionerna för formulärdata