How to rename named destinations in existing PDF files?

Tags: Named destinationsdestinationiText 7

I've been using named destinations in PDF files to open the PDF file at a specific location in the file. The team responsible for generating the PDF document uses a tool to automatically generated named destinations from book marks, so the named destinations tend to have names like 9_Glossary or Additional_Information. We've been asked to produce the same documents in multiple languages. I expect the we will be supplied PDF documents in multiple foreign languages with bookmarks in the same locations, but the names of the book marks will of course be in these other languages, and the automatically generated named destinations will be in the foreign language. I would like the named destinations in all the documents to be the same.

I can't be the first person to run into this problem, so I'm interested to see if others have dealt with this.

One thought that comes to might might be to rename the destinations in the foreign language documents. I have used iTextSharp to extract a list of named destinations. Is it possible to iTextSharp to rename those destinations? Ideally, I'd have a tool that my translator could use to match the named destination names in each language, then have the tool replace the named destination names.

Another thought is to maintain a database where the translation is performed in real time; the translator still has to match of named destination names, but they are stored in a database. The program that orders Adobe Reader to open would use the English version to look up the foreign language name and then use that to open the document.

Posted on StackOverflow on Nov 21, 2013 by Stephen Lewis

Please take a look at the example RenameDestinations for iText 7. It's doing more than you need, because the original document itself contains links to the named destinations and for those to keep working, we need to change the action that refers to the names we've changed.

This is the part that is relevant to you:

PdfDictionary catalog = pdfDoc.getCatalog().getPdfObject();
PdfDictionary names = catalog.getAsDictionary(PdfName.Names);
PdfDictionary dests = names.getAsDictionary(PdfName.Dests);
PdfArray name = dests.getAsArray(PdfName.Names);
for (int i = 0; i < name.size(); i += 2) {
    PdfString original = name.getAsString(i);
    PdfString newName = new PdfString("new" + original.toString());
    name.set(i, newName);

First you get the root dictionary (or catalog). You get the /Names dictionary, looking for named destinations (/Dests). In my case, I have a simple array with pairs of PdfString and references to PdfArray values. I replace all the string values with new names.

The structure I'm changing like this, is a name tree, and it usually isn't that linear. In your PDF, this tree can have branches, so you may want to write a recursive method to go through those branches. I don't have the time to write a more elaborate example, nor do I want to steal your job for you. This example should help you on your way.

Note that I keep track of the original and new names in a Map named renamed. I use this map to change the destinations of the Link annotations on the first page.

Click this link if you want to see how to answer this question in iText 5.