Imate deset tisoč pogodb v obliki PDF iz ducata različnih generatorjev, pravna služba pa želi, da ima vsaka izmed njih pravilnega Author (avtorja), popravljen niz Producer (proizvajalca) in bralni način, ki ob zagonu odpre ploščo z zaznamki. Naivna rešitev je, da naložite vsako datoteko, znova razporedite strani in zapišete nov dokument. S tem bi zavrgli vsako obstoječo številko objekta, zgodovino inkrementalnih posodobitev, morebitne digitalne podpise in skrbno prilagojeno navzkrižno referenco (xref), ki jo je ustvarilo prvotno orodje. Strani so videti enake, vendar je datoteka strukturno tujec. Za preprosto urejanje metapodatkov je to povsem napačna zamenjava
Pravilna poteza je, da naloženi dokument obravnavate kot graf objektov, ki ga spreminjate na mestu (in place): posezite v slovar Info, tok /Metadata in katalog (Catalog), spremenite tistih nekaj vnosov, ki vas zanimajo, in zapišite rezultat nazaj. HotPDF, izvorna komponenta VCL PDF za Delphi in C++Builder, ponuja natanko ta vmesnik prek svojega pisalnega API-ja za naložene dokumente. Ta članek govori o njegovi pravilni uporabi in o eni napaki, ki jo naredi skoraj vsak: urejanju slovarja Info ob pozabi, da druga kopija istih metapodatkov živi v formatu XMP
Dve mesti shranjujeta iste metapodatke, vendar se ne ujemata
Format PDF prenaša informacije o dokumentu na dveh vzporednih mestih, kar je vir večine težav z naslovom "spremenil sem naslov, vendar Acrobat še vedno prikazuje starega". Prvo mesto je slovar informacij o dokumentu, klasični objekt /Info s ključi /Title, /Author, /Subject, /Keywords, /Creator in /Producer, opredeljen v standardu ISO 32000-1 §14.3.3. Drugo mesto je paket XMP, XML dokument, shranjen kot tok, ki visi iz kataloga pod /Metadata, opredeljen v §14.3.2 in zgrajen na podatkovnem modelu Adobe XMP
Oba lahko vsebujeta naslov. Nič v specifikaciji ju ne sili k ujemanju. Sodobni pregledovalniki in večina validatorjev PDF/A imajo raje paket XMP, ko je ta prisoten, in se vrnejo na slovar Info, ko ga ni. Če torej posodobite le /Info — kar počne velika večina kode za nastavljanje metapodatkov PDF —, bo bralnik, ki zaupa XMP-ju, še naprej prikazoval zastarelo vrednost, preverjevalnik PDF/A pa bo označil neujemanje. Pravilna operacija na kateri koli datoteki, ki že ima paket XMP, je dvojno pisanje: spremenite vnos Info in ponovno generirajte XMP, da ostaneta usklajena. HotPDF vam ponuja obe polovici; doslednost njune skupne uporabe pa je na vas
Urejanje slovarja Info
Pomožne funkcije na strani Info so preproste in predvidljive. Metode SetLoadedTitle, SetLoadedAuthor, SetLoadedSubject, SetLoadedKeywords, SetLoadedCreator in SetLoadedProducer vsaka sprejmejo en AnsiString in zapišejo ustrezen ključ v naloženi slovar Info, pri čemer zamenjajo vrednost, če ključ že obstaja, ali jo dodajo, če ne. Če želite ključ v celoti odstraniti — na primer razkrit /Creator, ki poimenuje vaše interno orodje —, pokličite RemoveLoadedInfoKey z golim imenom ključa. Nobena od teh metod se ne dotika XMP-ja; delujejo izključno na objektu /Info, ki ga je LoadFromFile lociral ob razčlenjevanju datoteke
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('contract-in.pdf', '') > 0 then
begin
Pdf.SetLoadedTitle('Master Services Agreement 2026');
Pdf.SetLoadedAuthor('Legal Department');
Pdf.SetLoadedSubject('Executed contract, retention 7 years');
Pdf.SetLoadedKeywords('contract; MSA; 2026; executed');
Pdf.SetLoadedProducer('Acme Document Pipeline');
Pdf.RemoveLoadedInfoKey('Creator'); // drop the originating tool name
Pdf.SaveLoadedDocument('contract-out.pdf');
end;
finally
Pdf.Free;
end;
end;
Ena podrobnost, ki jo je treba upoštevati: te metode sprejemajo AnsiString. Za naslove ASCII to ne predstavlja težave, vendar morajo biti besedilni nizi PDF, ki potrebujejo ne-latinske znake, kodirani, kot zahteva specifikacija — UTF-16BE z oznako zaporedja bajtov (BOM) ali PDFDocEncoding —, preden jih posredujete. Knjižnica zapiše bajte, ki ji jih posredujete, v objekt niza; kodiranja ne ugiba namesto vas. Če so vaši naslovi v navadni angleščini, to prezrite. Če vsebujejo šumnike, naglase ali znake CJK, jih kodirajte premišljeno in preizkusite v pravem pregledovalniku
Ponovno zapisovanje paketa XMP
Metoda SetLoadedXMPMetadata predstavlja drugo polovico dvojnega pisanja. Posredujte ji celoten paket XMP kot AnsiString in izvedla bo eno od dveh možnosti: če katalog že vsebuje referenco na tok /Metadata, bo zamenjala vsebino tega toka na mestu ter ohranila isto številko objekta; če tok metapodatkov ne obstaja, ga bo ustvarila, označila kot /Type /Metadata in /Subtype /XML, dodelila številko objekta in ga povezala iz kataloga. V obeh primerih dobite veljaven objekt metapodatkov, ki ga bodo pregledovalniki lahko prebrali
Sami priskrbite XML, kar pomeni, da nadzorujete shemo — dc:title, dc:creator, xmp:CreatorTool in tako naprej. To prinaša moč in odgovornost hkrati: knjižnica ne razčlenjuje in ne potrjuje vašega paketa, bajte pa zapiše nestisnjene, brez uporabljenega filtra toka. Nepravilno oblikovan paket bo nemoteno prešel skozi klic in se kasneje pojavil kot pritožba o pokvarjenih metapodatkih. XML zgradite skrbno in natančno zrcalite vrednosti, ki ste jih zapisali v slovar Info, da si oba pogleda nikoli ne bosta nasprotovala
const
XMP_TEMPLATE =
'<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>' +
'<x:xmpmeta xmlns:x="adobe:ns:meta/">' +
'<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">' +
'<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">' +
'<dc:title><rdf:Alt><rdf:li xml:lang="x-default">%s</rdf:li></rdf:Alt></dc:title>' +
'<dc:creator><rdf:Seq><rdf:li>%s</rdf:li></rdf:Seq></dc:creator>' +
'</rdf:Description></rdf:RDF></x:xmpmeta><?xpacket end="w"?>';
begin
// After setting the Info dictionary, mirror the same values into XMP:
Pdf.SetLoadedTitle('Master Services Agreement 2026');
Pdf.SetLoadedAuthor('Legal Department');
Pdf.SetLoadedXMPMetadata(
AnsiString(Format(XMP_TEMPLATE,
['Master Services Agreement 2026', 'Legal Department'])));
Pdf.SaveLoadedDocument('contract-out.pdf');
end;
Ta vrstni red — najprej Info, nato XMP in nato shranjevanje — je vzorec, ki ga je treba usvojiti. Klica sta neodvisna; doslednost obstaja le zato, ker ste jima posredovali enake nize. Če preskočite klic XMP na datoteki, ki ima paket XMP, se vrnete k hrošču tihe zastarelosti, za preprečevanje katerega je namenjen celoten ta razdelek

Upravljanje načina, kako pregledovalnik odpre datoteko
Trije vnosi v katalogu določajo, kaj bralec vidi v trenutku, ko se dokument odpre, in vsi trije so enovrstični popravki na naloženem grafu. Metoda SetLoadedPageMode zapiše /PageMode kot objekt imena: posredujte 'UseOutlines' za prikaz plošče z zaznamki, 'UseThumbs' za vrstico sličic, 'FullScreen' za predstavitveni način ali 'UseAttachments' za prikaz plošče s prilogami (ISO 32000-1 §7.7.3.1, tabela 28). Metoda SetLoadedPageLayout na enak način zapiše /PageLayout — 'SinglePage', 'OneColumn', 'TwoColumnLeft' in ostale. Obe metodi sprejmeta ime brez vodilne poševnice; knjižnica jo doda pri izhodu
Metoda SetLoadedLanguage zapiše vnos v katalogu /Lang, oznako naravnega jezika za dokument kot celoto — 'en-US', 'de-DE', oznako BCP 47. Upoštevajte razliko v vrstah objektov, ki pogosto povzroča zmedo: /PageMode in /PageLayout sta PDF objekta imena (name), medtem ko je /Lang niz (string). HotPDF to interno pravilno obravnava, če pa kdaj pregledate izhod, boste videli /PageMode /UseOutlines nasproti /Lang (en-US), in zdaj veste, zakaj. Vnos /Lang je pomembnejši, kot se zdi: to je tisto, kar berejo asistenčne tehnologije za izbiro izgovarjave, in je stroga zahteva za skladnost z dostopnostjo PDF/UA
if Pdf.LoadFromFile('handbook.pdf', '') > 0 then
begin
Pdf.SetLoadedPageMode('UseOutlines'); // /PageMode, a name
Pdf.SetLoadedPageLayout('TwoColumnLeft'); // /PageLayout, a name
Pdf.SetLoadedLanguage('en-US'); // /Lang, a string
Pdf.SaveLoadedDocument('handbook-tagged.pdf');
end;
Preimenovanje zaznamkov brez motenja drevesa
Naslovi zaznamkov so del rutinskega čiščenja — tipkarska napaka v naslovu, poglavje, preštevilčeno po izgradnji kazala. Metoda SetLoadedOutlineTitle sprejme z nič indeksirani indeks med vnosi kazala na najvišji ravni in nov naslov, se sprehodi skozi verigo katalog → /Outlines → /First → /Next do tega mesta in zamenja niz /Title tega vnosa. Spremeni le naslov; cilj, stanje odprto/zaprto in struktura otrok ostanejo nedotaknjeni
if Pdf.LoadFromFile('report.pdf', '') > 0 then
begin
Pdf.SetLoadedOutlineTitle(0, 'Executive Summary');
Pdf.SetLoadedOutlineTitle(1, 'Financial Results');
Pdf.SaveLoadedDocument('report-renamed.pdf');
end;
Kako shranjevanje ostane na mestu
Vsako zgoraj opisano urejanje spreminja objekte v pomnilniku; nič ne doseže diska, dokler se ne zažene SaveLoadedDocument. Razlog, zakaj je ta pristop povsem naraven, je v tem, da shranjevanje ne regenerira dokumenta — ohrani obstoječe številke objektov in strukturo, ki jo je HotPDF razčlenil ob nalaganju, ter zapiše nazaj enak graf z vašo peščico spremenjenih in na novo dodeljenih objektov. To je tisto, kar preprečuje, da bi prehod metapodatkov prepisal celotno datoteko, in to je enak mehanizem posodabljanja na mestu, ki omogoča delovanje tokov objektov in inkrementalnih posodobitev. Če vaše izvorne datoteke prihajajo iz programa Word ali druge pisarniške zbirke, ima njihova razporeditev objektov svoje posebnosti, ki jih je vredno poznati pred urejanjem; članek o tokovih navzkrižnih referenc s hibridnimi referencami v pisarniških dokumentih PDF opisuje, kako so te datoteke strukturirane in kaj preživi povratno potovanje (round trip)
Dve meji, ki ju je treba spoštovati. Prvič, to je model urejanja na mestu in ne orodje za redakcijo ali čiščenje: odstranitev ključa Info odstrani ta ključ, vendar ne počisti starejših vrednosti, ki bi lahko ostale v prejšnji generaciji inkrementalnih posodobitev iste datoteke. Če je vaša zahteva resnična odstranitev občutljivih metapodatkov, gre za drugačno, zahtevnejšo operacijo. Drugič, zapis XMP je dobeseden — knjižnica zaupa vašemu XML-ju in ga ne potrjuje —, zato za vse, kar je namenjeno PDF/A ali strogemu validatorju, generirajte paket iz znane dobre predloge in preverite izhod. Uporabljeno znotraj teh meja je urejanje metapodatkov na mestu orodje prave velikosti: popravi tistih nekaj bajtov, ki so napačni, in pusti devetindevetdeset odstotkov datoteke, ki je bila že prej pravilna, natanko takšno, kot jo je zapisal prvotni proizvajalec
API za pisanje v naložene dokumente, prikazan tukaj, se prinaša s standardno komponento HotPDF Component za Delphi in C++Builder, skupaj s celotnim naborom metod za urejanje metapodatkov, kazala in kataloga