'Change order of pdf bookmarks using PyPdf2

I create an application, that merges multiple pdfs with a bookmark. If the origin pdfs already have bookmarks, I want to keep them and just add a bookmark at the beginning of the pdf. I use the following code: The title and the path in the code come from user input.

from PyPDF2 import PdfFileReader, PdfFileMerger
from PyPDF2.utils import PdfReadError

merger = PdfFileMerger()
pages_total = 0
for path, title in zip(paths, titles):
    merger.append(path, import_bookmarks=True)
    with open(path, "rb") as file:
           pdf = PdfFileReader(file, "rb")
           pages_one = pdf.getNumPages()
           pages_total += pages_one

    merger.addBookmark(f"{title}", pages_total - pages_one, parent=None)

 save_path = input() + ".pdf"  
 merger.write(save_path)
 merger.close()

The new pdf has all bookmarks, that points to the right pages. However, that bookmark for the entire pdf appears after the pdfs that already existed. How can I change the order in which the bookmarks are displayed?

The picture below hopefully clarifies the problem. The last bookmark was added and should be the first in the list.

enter image description here



Solution 1:[1]

I found a solution. First I create a parent bookmark with the the pdf title. Then I get all existing bookmarks in the pdf with pdf.getOutlines() and iterate over the output:

parent = merger.addBookmark(f"{title}", pages_total - pages_one, parent=None)
for i in pdf.getOutlines():
     if isinstance(i, list):  # if nested bookmarks exists
         nested_boomarks(parent=child, bookmarks=i, merger=merger, pdf=pdf)
     else:
         child = merger.addBookmark(i["/Title"], pdf.getDestinationPageNumber(i), parent=parent)
                           

When there are bookmarks inside the bookmarks I use this recursive function.

def nested_boomarks(parent, bookmarks, merger, pdf):
        for i in bookmarks:
            if isinstance(i, list):
                nested_boomarks(child, i, merger, pdf)
            else:
                child = merger.addBookmark(i["/Title"], pdf.getDestinationPageNumber(i), parent=parent)

This way I get the following output: enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mazze