Enumerate named destinations

605 Views Asked by At

I am playing with iText 7 and I have a problem with getting a list of named destinations.

With previous version 5 it was very easy with helper:

using (var reader = new PdfReader(_file))
{
    var items = SimpleNamedDestination.GetNamedDestination(reader, false).Select(o => o.Key).ToList();
    ...
}

In 7 I can't find helper anymore and have to use this monstrosity (adapted code from official java example):

using (var reader = new PdfDocument(new PdfReader(file)))
{
    var catalog = reader.GetCatalog().GetPdfObject();
    var names = catalog.GetAsDictionary(PdfName.Names);
    var dests = names.GetAsDictionary(PdfName.Dests);
    var name = dests.GetAsArray(PdfName.Names); // problem

    var items = new List<string>();
    for (int i = 0; i < name.Size(); i += 2)
        items.Add(name.GetAsString(i).ToString());
    ...
}

Moreover, for some PDFs this code fails with NullReferenceException due to null returned at GetAsArray line.

Looking closely at PdfDictionary and PdfArray types - they have only 1 entry, no enumerator (!), no LINQ support.

My questions:

  • (opinion based, but I am curious to hear the answer) Why iText 7 has less functionality than 5? Im I suppose to mix both?
  • (request for off-site resource) Is there proper C# iText 7 documentation somewhere? Converting from java and filtering dozens of questions about it on SO is pretty inefficient.
  • (a bit of rant) how the hell I am supposed to debug those types? Talking about PdfDictionary, it shows 1 entry, probably not yet parsed content of PDF. I want to see why GetAsArray fails, but there is no way for me to debug it.
  • (actual question) Why above code fails for some pdf containing named destination (e.g. this one, but I have many more locally)?

Am I doing something wrong?

1

There are 1 best solutions below

0
On BEST ANSWER

I don't know C#, but in Java, one would get the name tree with the getNameTree() method. I assume a similar method GetNameTree() exists in the C# version of iText 7:

Map<String, PdfObject> names =
    pdfDoc.getCatalog().getNameTree(PdfName.Dests).getNames();
for (Map.Entry<String, PdfObject> name : names.entrySet()) {
    System.out.println("Name = " + name.getKey());
    System.out.println("Page = " + name.getValue().toString());
}

It would be great if you could update my answer with the C# syntax if it turns out that my answer is helpful.


C#:

using (var pdf = new PdfDocument(new PdfReader(file)))
{
    var names = pdf.GetCatalog().GetNameTree(PdfName.Dests).GetNames().Select(o => o.Key).ToList();
    ...
}