从文档大纲(书签)中获取页码
Get the page number from document outline (bookmarks)
我正在使用 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() on Github (same for java 的 Net 实现。我不明白此方法的参数的用途。如果我传入 null,它似乎适用于使用 ToString() 在大纲层次结构中仅使用一个级别的 pdf。通过工作我的意思是它 returns 零索引页码作为一个字符串。对于 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");
}
}
}
所以我还在想办法解决这个问题。
关于大纲层次结构的级别,为了遍历整个层次结构,您必须检查每个 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
。
我正在使用 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() on Github (same for java 的 Net 实现。我不明白此方法的参数的用途。如果我传入 null,它似乎适用于使用 ToString() 在大纲层次结构中仅使用一个级别的 pdf。通过工作我的意思是它 returns 零索引页码作为一个字符串。对于 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");
}
}
}
所以我还在想办法解决这个问题。
关于大纲层次结构的级别,为了遍历整个层次结构,您必须检查每个 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
。