PDFlibPas zet PDF-inhoud om naar twee bewerkbare formaten zonder Office-automatisering. ExportPageMarkdown en ExportDocumentMarkdown geven semantische Markdown terug met afgeleide koppen, geordende en ongeordende lijsten en pipe-tabellen, terwijl SaveDOCXToFile en SaveDOCXToStream een WordprocessingML-package schrijven met paragrafen, koppen, native lijstnummering, gedetecteerde tabellen, fontopmaak, pagina-einden en gepositioneerde PNG-afbeeldingen
Beide draaien volledig in Pascal, op een server, zonder geïnstalleerd Word en zonder COM. Die beperking is de reden waarom deze functie in een PDF-bibliotheek zit in plaats van in een desktoptool
Waarom is "PDF naar Word" werkelijk lastig?
Omdat een PDF-pagina geen paragrafen bevat. Ze bevat tekstweergave-operatoren die reeksen glyphs op coördinaten plaatsen, in welke volgorde de producent ze ook maar heeft weggeschreven, zonder enige verplichting om aan te geven dat twee reeksen bij dezelfde zin horen, laat staan bij hetzelfde lijstitem. Het formaat is ontworpen om een gedrukte pagina exact te beschrijven, en het slaagt daarin door precies de structuur weg te gooien die de pagina heeft voortgebracht
Dus elke converter moet reconstrueren wat de generator heeft weggegooid. Regelgroepering komt uit verticale afstand en baselineuitlijning. Alineagrenzen komen uit veranderingen in afstand en inspringing. Een kop is een regel waarvan het font groter of zwaarder is dan de hoofdtekst en die apart staat van wat erop volgt. Een lijst is een reeks alinea's die begint met een opsommingsteken of een nummerpatroon. Een tabel is een raster van tekstblokken waarvan de randen over rijen en kolommen heen uitlijnen. Elk van die zaken is een gevolgtrekking, en gevolgtrekking betekent een goed resultaat bij documenten die gewone typografische conventies volgen, en een middelmatig resultaat bij documenten die dat niet doen
Getagde PDF's zijn de uitzondering, en een grote. Wanneer het document een structuurboom draagt, worden de rollen van alinea, kop, lijst en tabel geregistreerd in plaats van geraden, wat verklaart waarom het toegankelijkheidswerk beschreven in de structuur voor toegankelijkheid van getagde PDF's zich ook uitbetaalt in conversiekwaliteit. Als u de producent zelf beheert, is het taggen van uw output het meest hefboomrijke dat u kunt doen voor iedereen die het later moet converteren
Markdown-export, pagina voor pagina
Het Markdown-pad is degene waarnaar u grijpt wanneer de bestemming een tekstpijplijn is: een documentatiesite, een zoekindex, een retrievalcorpus voor een assistent. Opties vormen een bitmasker: PDF_MARKDOWN_INCLUDE_PAGE_MARKERS, PDF_MARKDOWN_DETECT_HEADINGS, PDF_MARKDOWN_PRESERVE_STYLES, waarbij PDF_MARKDOWN_DEFAULT alle drie combineert
var
Pdf: TPDFlib;
Md: WideString;
begin
Pdf := TPDFlib.Create;
try
Pdf.LoadFromFile('handbook.pdf', '');
// Eén pagina, als string
Md := Pdf.ExportPageMarkdown(1, PDF_MARKDOWN_DEFAULT);
// Een paginabereik, gestreamd naar schijf als UTF-8 zonder BOM
Pdf.SaveMarkdownToFile('1-40',
PDF_MARKDOWN_DETECT_HEADINGS or PDF_MARKDOWN_PRESERVE_STYLES,
'handbook.md');
finally
Pdf.Free;
end;
end;
Paginamarkeringen verdienen zichzelf terug in retrievalwerk. Een tekstfragment dat de pagina draagt waar het vandaan komt, kan precies geciteerd worden, en een lezer die de verwijzing volgt, komt precies uit waar de bewering staat. Schakel ze uit wanneer de Markdown bestemd is voor menselijke lezing, waar paginagrenzen uit de brondaklay-out alleen ruis zijn
De streamende toegangspunten zijn van belang bij grote documenten. SaveMarkdownToStream en SaveMarkdownToFile schrijven UTF-8 één pagina tegelijk en bufferen de volledige output niet, dus een handleiding van 900 pagina's wordt niet eerst een string van 900 pagina's in het geheugen. Ook het ontbreken van een byte-order mark is bewust: een BOM in een Markdown-bestand brengt een verrassend aantal statische sitegeneratoren en diff-tools in de war
DOCX zonder Office op de machine
De DOCX-writer produceert het package zelf: ZIP-items geschreven als raw Deflate met CRC-controles, de WordprocessingML-onderdelen, en de relaties die ze verbinden. Er wordt niets naar Word aangeroepen, wat betekent dat de conversie draait op een headless server, binnen een serviceaccount, in een container, op alle plekken waar Office-automatisering ofwel ongelicentieerd, instabiel of verboden is
var
Pdf: TPDFlib;
Target: TFileStream;
begin
Pdf := TPDFlib.Create;
Target := TFileStream.Create('handbook.docx', fmCreate);
try
Pdf.LoadFromFile('handbook.pdf', '');
Pdf.SaveDOCXToStream('1-40',
PDF_DOCX_INCLUDE_IMAGES or PDF_DOCX_DETECT_HEADINGS or
PDF_DOCX_PRESERVE_STYLES or PDF_DOCX_PRESERVE_PAGE_BREAKS,
Target);
finally
Target.Free;
Pdf.Free;
end;
end;
Afbeeldingsgegevens worden weggeschreven terwijl elke pagina verwerkt wordt in plaats van verzameld en aan het einde toegevoegd, dus het piekgeheugen volgt één pagina in plaats van het hele document. De expliciete paginavolgorde blijft behouden, en de geselecteerde PDF-pagina wordt achteraf hersteld, wat van belang is wanneer de export één stap is binnen een langere taak die om andere redenen een pagina had geselecteerd
Wat levert deterministische packaging op?
Byte-voor-byte reproduceerbaarheid. Twee conversies van dezelfde input met dezelfde opties produceren hetzelfde package, wat betekent dat u de output kunt hashen om wijzigingen te detecteren, twee builds van een gegenereerd document kunt diffen, en agressief kunt cachen zonder u zorgen te maken dat een identieke input een ander artefact opleverde
Office-automatisering kan dat niet beloven. Ze sluit tijdstempels, revisie-identificatoren en machineafhankelijke metadata in, dus hetzelfde document twee keer converteren levert verschillen op die hashing ondermijnen. Dezelfde redenering drijft de deterministische bestands-ID's die besproken worden in deterministische PDF-ID's voor reproduceerbare builds: wanneer output reproduceerbaar is, wordt verificatie een vergelijking in plaats van een inspectie
Waar de output goed is, en waar niet
Wees hierover eerlijk tegen uw gebruikers, want de conversiekwaliteit varieert meer met de input dan met de converter. Getagde PDF's en netjes gegenereerde zakelijke documenten, facturen, rapporten, contracten, converteren goed: koppen komen als koppen aan, tabellen overleven, lijsten hernummeren correct in Word. Tweekoloms academische lay-outs converteren behoorlijk als de kolomgeometrie regelmatig is. Tabellen die over paginagrenzen lopen, worden door gevolgtrekking opnieuw samengesteld en soms gesplitst. Sterk vormgegeven marketingmateriaal, waar tekst voor visueel effect geplaatst is in plaats van in leesvolgorde, converteert slecht, en geen hoeveelheid gevolgtrekking lost dat op
Gescande documenten zijn een apart geval. Een pagina die één grote afbeelding is, bevat geen tekstobjecten, dus is er niets te exporteren totdat er een tekstlaag bestaat; het OCR-pad dat er een oplevert, is een voorwaarde, geen optie. Neem vóór een grote batch een steekproef van een tiental representatieve bestanden en bekijk de output, en overweeg eerst paginaelementen te inventariseren, zoals beschreven in tekstzoeken en het inventariseren van paginaelementen, om te zien wat de pagina's daadwerkelijk bevatten
Voor assistent- en retrievalpijplijnen is het Markdown-pad meestal het betere doel: koppen worden chunkgrenzen, tabellen blijven leesbaar als pipe-tabellen, en paginamarkeringen geven elke chunk een citeerbare locatie. Voor menselijke bewerking is DOCX het antwoord, want wat de gebruiker wil, is niet de tekst maar de mogelijkheid om die te wijzigen
PDFlibPas is een PDF-bibliotheek voor Delphi, C++Builder en Lazarus met bijpassende DLL- en ActiveX-interfaces, dus dezelfde exportaanroepen zijn ook beschikbaar vanuit C#, C++ of scripting-hosts. Volledige documentatie en een proefversie staan op de PDFlibPas Delphi PDF-bibliotheekpagina