2017-10-12 8 views
0

J'utilise la bibliothèque itext7 pour manipuler certains fichiers PDF existants. Pour une raison quelconque, je ne suis pas en mesure d'obtenir le numéro de page à partir du contour. Je suppose que je devrais en quelque sorte l'obtenir à partir du PdfDestination mais je ne trouve aucune méthode correspondante dans aucune de ses sous-classes.Obtenir le numéro de page à partir du plan du document (signets)

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 
} 

En iText5 j'ai utilisé le SimpleBookmark.GetBookmark(reader) qui a renvoyé une liste de dictionnaires contenant une entrée « Page » - mais cette fonctionnalité semble avoir été retiré iText7.

Edit: J'ai eu un coup d'œil à la mise en œuvre nette de PdfExplicitDestination.getDestinationPage() sur Github (même pour java Je ne comprends pas le but des paramètres à cette méthode si je passe null, il semble travailler.. pdfs qui utilise seulement un niveau dans la hiérarchie de plan en utilisant ToString() En travaillant je veux dire qu'il retourne le numéro de page indexé par zéro comme une chaîne.Pour le code PDF il ne trouve pas le numéro de page (ni pour le premier niveau) .

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"); 
     }  
    } 
} 

J'essaie toujours de comprendre.

Répondre

1

En ce qui concerne les niveaux de la hiérarchie des contours, afin de parcourir toute la hiérarchie, vous devrez vérifier les enfants de PdfOutline et les parcourir récursivement.

Le paramètre names qui vous était confus est le paramètre responsable de la résolution des destinations nommées nécessaire pour obtenir correctement les numéros de page car votre document PDF peut contenir des destinations explicites et des destinations nommées. Pour obtenir la carte des noms, vous pouvez utiliser pdfDocument.getCatalog().getNameTree(PdfName.Dests).getNames(); Pour trouver le numéro de page d'un objet de page, vous devez utiliser pdfDocument.getPageNumber(PdfDictionary).

Dans l'ensemble, la méthode marche à travers les contours peuvent se présenter comme suit:

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); 
    } 
} 

Et le principal point d'entrée pour appeler la méthode pour traverser la racine de contour:

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

S'il vous plaît noter que le L'exemple de code est pour Java, mais il devrait être similaire en C# à l'exception de quelques changements de cas et IDictionary à la place si Map.

+0

Merci beaucoup. C'était plus compliqué que prévu! –