【问题标题】:C# / PdfSharp: Find out page number from bookmark entries and splitC# / PdfSharp:从书签条目中找出页码并拆分
【发布时间】:2026-02-14 01:50:01
【问题描述】:

尝试处理 PDF 文件并使用使用 PDFSharp 定义的书签将其拆分,虽然我可以获得书签列表,但我无法弄清楚如何实际找出与书签定义相对应的页码。

我正在使用的示例 PDF 文件在第 1、5 和 6 页上定义了三个*书签,虽然我可以看到下面带有 sn-p 的书签,但我无法找到映射书签的方法到页码。

代码:

using (PdfDocument document = PdfReader.Open("test.pdf", PdfDocumentOpenMode.Import))
{
    PdfDictionary outline = document.Internals.Catalog.Elements.GetDictionary("/Outlines");

    Console.WriteLine("Page count: " + document.PageCount);

    foreach(var page in document.Pages)
    {
        // any hierarchy info on the page itself? doesn't seem to have any.
        Console.WriteLine(page.ToString());

    }

    for (PdfDictionary child = outline.Elements.GetDictionary("/First"); child != null; child = child.Elements.GetDictionary("/Next"))
    {
        Console.WriteLine(child.Elements.GetString("/Title"));

        // FIXME: get page numbers?

    }

}

输出:

Page count: 9
<< /Contents [ 1019 0 R ] /Group << /CS /DeviceRGB /S /Transparency >> /MediaBox [ 0 0 3874 2667 ] /Parent 1 0 R /Resources 1018 0 R /Type /Page >>
<< /Contents [ 1022 0 R ] /Group << /CS /DeviceRGB /S /Transparency >> /MediaBox [ 0 0 3874 2667 ] /Parent 1 0 R /Resources 1021 0 R /Type /Page >>
<< /Contents [ 1025 0 R ] /Group << /CS /DeviceRGB /S /Transparency >> /MediaBox [ 0 0 3874 2667 ] /Parent 1 0 R /Resources 1024 0 R /Type /Page >>
<< /Contents [ 1028 0 R ] /Group << /CS /DeviceRGB /S /Transparency >> /MediaBox [ 0 0 3874 2667 ] /Parent 1 0 R /Resources 1027 0 R /Type /Page >>
<< /Contents [ 1032 0 R ] /Group << /CS /DeviceRGB /S /Transparency >> /MediaBox [ 0 0 842 595 ] /Parent 1 0 R /Resources 1031 0 R /Type /Page >>
<< /Annots [ 46 0 R 48 0 R 50 0 R 52 0 R 54 0 R 56 0 R 58 0 R 60 0 R 62 0 R 64 0 R 66 0 R 68 0 R 70 0 R 72 0 R 74 0 R ] /Contents [ 1043 0 R ] /Group << /CS /DeviceRGB /S /Transparency >> /MediaBox [ 0 0 1130 799 ] /Parent 1 0 R /Resources 1042 0 R /Type /Page >>
<< /Annots [ 82 0 R 84 0 R 86 0 R 88 0 R 90 0 R 92 0 R 94 0 R 96 0 R 98 0 R 100 0 R 102 0 R 104 0 R 106 0 R 108 0 R 110 0 R 112 0 R 114 0 R 116 0 R 118 0 R 120 0 R 122 0 R 124 0 R 126 0 R 128 0 R 130 0 R 132 0 R 134 0 R 136 0 R 138 0 R 140 0 R 142 0 R 144 0 R 146 0 R 148 0 R 150 0 R 152 0 R 154 0 R 156 0 R 158 0 R ] /Contents [ 1048 0 R ] /Group << /CS /DeviceRGB /S /Transparency >> /MediaBox [ 0 0 1130 799 ] /Parent 1 0 R /Resources 1047 0 R /Type /Page >>
<< /Annots [ 166 0 R 168 0 R 170 0 R 172 0 R 174 0 R 176 0 R 178 0 R 180 0 R 182 0 R ] /Contents [ 1053 0 R ] /Group << /CS /DeviceRGB /S /Transparency >> /MediaBox [ 0 0 1130 799 ] /Parent 1 0 R /Resources 1052 0 R /Type /Page >>
<< /Annots [ 190 0 R 192 0 R 194 0 R 196 0 R ] /Contents [ 1058 0 R ] /Group << /CS /DeviceRGB /S /Transparency >> /MediaBox [ 0 0 1130 799 ] /Parent 1 0 R /Resources 1057 0 R /Type /Page >>
Bookmark 1
Bookmark 2 
Bookmark 3

我不一定嫁给 PDFSharp 库。

有什么建议吗?谢谢!

【问题讨论】:

    标签: c# pdf pdfsharp


    【解决方案1】:

    PDFSharp 的维护者在这里提供了一些对此问题的见解:http://forum.pdfsharp.net/viewtopic.php?f=2&t=3663

    【讨论】:

      【解决方案2】:

      我知道这是一个较老的问题,但我想帮忙,因为我最近遇到了同样的事情。我需要根据书签拆分文档。我查看了“/Dest”,但无法使用。原来关键是将 child 设置为 PdfOutline 类型。

      此代码获取根书签并将所述根+子项移动到其自己的文档保存书签中。我知道这些天没有人使用 VB,但它应该很容易转换为 C#。

      注意:您需要在导入模式PdfSharp.Pdf.IO.PdfReader.Open(path, PdfSharp.Pdf.IO.PdfDocumentOpenMode.Import) 中打开原始文档。

      Dim rgx As New Regex("^[0-9]{16}$")
      Dim docs As List(Of PdfDocument) = New List(Of PdfDocument)
      Dim i As Integer = 0
      Dim p As String = Application.UserAppDataPath + "\part{0}.pdf"
      ' Root Level Bookmarks
      For Each rootb In document.Outlines
          ' Ensure Account Number Type
          If rgx.IsMatch(rootb.Title) Then
              Dim newdoc As PdfSharp.Pdf.PdfDocument = New PdfDocument
              Dim rp As PdfPage = newdoc.AddPage(rootb.DestinationPage)
              Dim outline As PdfOutline = newdoc.Outlines.Add(rootb.Elements.GetString("/Title"), rp, True, PdfOutlineStyle.Bold, XColors.Red)
              Dim child As PdfDictionary = rootb.Elements.GetDictionary("/First")
              While child IsNot Nothing
                  Dim item As PdfOutline = child
                  Dim cp As PdfPage = newdoc.AddPage(item.DestinationPage)
                  outline.Outlines.Add(item.Elements.GetString("/Title"), cp, True)
                  child = child.Elements.GetDictionary("/Next")
              End While
      
              newdoc.Save(String.Format(p, i))
              i += 1
      Next
      

      【讨论】: