Java PDFBox список всех названных мест назначения страницы - PullRequest
0 голосов
/ 05 сентября 2018

Для моего проекта Java мне нужно перечислить все именованные места назначения на странице PDF.

PDF и его имя назначения создаются с помощью LaTeX (с помощью команды hypertarget ), например следующим образом:

\documentclass[12pt]{article}
\usepackage{hyperref} 

\begin{document}

\hypertarget{myImportantString}{}   % the anchor/named destination to be extracted "myImportantString"

Empty example page

\end{document}

Как извлечь все именованные места назначения конкретной страницы этого документа PDF с помощью библиотеки PDFBox версии 2.0.11?

Я не смог найти какой-либо рабочий код для этой проблемы в Интернете или PDFBox examples . Это мой текущий (минимизированный) код:

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;

import java.io.File;
import java.util.List;

public class ExtractNamedDests {

    public static void main(String[] args) {

        try {

            int c = 1;
            PDDocument document = PDDocument.load(new File("<path to PDF file>"));

            for (PDPage page : document.getPages()) {
                System.out.println("Page " + c + ":");

                // named destinations seem to be no type of annotations since the list is always empty:
                List<PDAnnotation> annotations = page.getAnnotations();
                System.out.println("    Count annotations: " + annotations.size());

                // How to extract named destinations??
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

В этом примере я хочу извлечь строку "myImportantString" со страницы в Java.

РЕДАКТИРОВАТЬ: Вот пример PDF-файл . Я использую PDFBox версии 2.0.11.

1 Ответ

0 голосов
/ 07 сентября 2018

Я нашел решение с помощью Tilman Hausherr . Он использует код, который он предложил в своих комментариях.

Метод getAllNamedDestinations() возвращает карту всех именованных адресатов в документе (не аннотации) с именем и адресатом. Именованные места назначения могут быть глубоко вложены в документ. Поэтому метод traverseKids() рекурсивно находит все вложенные именованные места назначения.

public static Map<String, PDPageDestination> getAllNamedDestinations(PDDocument document){

        Map<String, PDPageDestination> namedDestinations = new HashMap<>(10);

        // get catalog
        PDDocumentCatalog documentCatalog = document.getDocumentCatalog();

        PDDocumentNameDictionary names = documentCatalog.getNames();

        if(names == null)
            return namedDestinations;

        PDDestinationNameTreeNode dests = names.getDests();

        try {
            if (dests.getNames() != null)
                namedDestinations.putAll(dests.getNames());
        } catch (Exception e){ e.printStackTrace(); }

        List<PDNameTreeNode<PDPageDestination>> kids = dests.getKids();

        traverseKids(kids, namedDestinations);

        return namedDestinations;
    }

private static void traverseKids(List<PDNameTreeNode<PDPageDestination>> kids, Map<String, PDPageDestination> namedDestinations){

    if(kids == null)
        return;

    try {
        for(PDNameTreeNode<PDPageDestination> kid : kids){
            if(kid.getNames() != null){
                try {
                    namedDestinations.putAll(kid.getNames());
                } catch (Exception e){ System.out.println("INFO: Duplicate named destinations in document."); e.printStackTrace(); }
            }

            if (kid.getKids() != null)
                traverseKids(kid.getKids(), namedDestinations);
        }

    } catch (Exception e){
        e.printStackTrace();
    }
}
...