从文档大纲(书签)中获取页码

时间:2017-10-12 18:29:41

标签: c# itext itext7

我正在使用itext7库来操作一些现有的PDF。出于某种原因,我无法从大纲中获取页码。我想我不知何故应该从PdfDestination获得它,但在其任何子类中都找不到任何匹配的方法。

PdfDocument pdfDoc =  new PdfDocument(new PdfReader("example.pdf"));
var root = pdfDoc.GetOutlines(false);
foreach (PdfOutline ol in root.GetAllChildren()) {
    Console.WriteLine(ol.GetTitle());
    PdfDestination d =  ol.GetDestination();
    // how to get the page number from the destination object
}

在iText5中,我使用SimpleBookmark.GetBookmark(reader)返回了一个包含" Page"输入 - 但这个功能似乎已在iText7中删除。

修改 我查看PdfExplicitDestination.getDestinationPage()Github的网络实施情况({3}}也一样。我不了解此方法参数的用途。如果我传入null它似乎适用于仅使用ToString()在大纲层次结构中使用一个级别的pdf。通过工作我的意思是它将零索引页码作为字符串返回。对于PDF代码,它没有找到页码(两者都没有为第一级)。

PdfDocument pdfDoc =  new PdfDocument(new PdfReader("example.pdf"));
var root = pdfDoc.GetOutlines();
foreach (PdfOutline ol in root.GetAllChildren()) {
    Console.WriteLine(ol.GetTitle());
    var d = ol.GetDestination();
    if (d is PdfExplicitDestination) {
        string PageNoStr = d.GetDestinationPage(null).ToString();               
        // this is the content of the method (less the ToString()
        //string PageNoStr = ((PdfArray)d.GetPdfObject()).Get(0).ToString();
        int pageNo;
        if (Int32.TryParse(PageNoStr, out pageNo)) {
            Console.WriteLine("Page is " + pageNo);
        } else  {
            Console.WriteLine("Error page");
        }    
    }
}

所以我仍然想弄清楚这一点。

1 个答案:

答案 0 :(得分:2)

关于大纲层次结构的级别,为了遍历整个层次结构,您必须检查每个PdfOutline的子级并以递归方式遍历它们。

让您感到困惑的名称参数是负责解析命名目标的参数,这通常是正确获取页码所必需的,因为您的PDF文档可能包含显式目标和命名目标。要获取名称映射,您可以使用pdfDocument.getCatalog().getNameTree(PdfName.Dests).getNames();

要按页面对象查找页码,您应使用pdfDocument.getPageNumber(PdfDictionary)

总体而言,遍历大纲的方法可能如下所示:

void walkOutlines(PdfOutline outline, Map<String, PdfObject> names, PdfDocument pdfDocument) {
    if (outline.getDestination() != null) {
        System.out.println(outline.getTitle() + ": page " +
                pdfDocument.getPageNumber((PdfDictionary) outline.getDestination().getDestinationPage(names)));
    }
    for (PdfOutline child : outline.getAllChildren()) {
        walkOutlines(child, names, pdfDocument);
    }
}

调用方法遍历大纲根目录的主要入口点:

PdfNameTree destsTree = pdfDocument.getCatalog().getNameTree(PdfName.Dests);
PdfOutline root = pdfDocument.getOutlines(false);
walkOutlines(root, destsTree.getNames(), pdfDocument);

请注意,代码示例适用于Java,但在C#中应该类似,除了一些案例更改,而IDictionary代替Map