Skip to content

Bookmark

Foxit PDF SDK provides a navigation tool called bookmarks that allows users to quickly locate and link to the parts of their interest in PDF documents. PDF bookmarks are also called outlines, and each bookmark contains a target location or action to describe the location it links to. It is a tree-shaped hierarchical structure, so before accessing the bookmark tree, you must first obtain the root node of the entire bookmark tree. Here, the bookmark root node is an abstract object, which has only some child nodes, no sibling nodes, and no data (including bookmark data, target position data and action data).

Take the Java development language as an example:

To get the root node of the entire bookmark tree, use the pdf.PDFDoc.getRootBookmark interface. Because it does not have any data, it cannot be displayed on the application interface. The only interface that can be called is Bookmark.getFirstChild.

After obtaining the bookmark root node, you can call the following interface to access other bookmarks:

  • To access the parent bookmark, use the Bookmark.getParent interface.
  • To access the first child bookmark, use the Bookmark.getFirstChild interface.
  • To access the next sibling bookmark, use the Bookmark.getNextSibling interface.
  • To insert a new bookmark, use the Bookmark.insert interface.
  • To move a bookmark, use the Bookmark.moveTo interface.

Traverse all bookmarks in the PDF document

c++
#include "include/common/fs_common.h"
#include "include/pdf/fs_filespec.h"
#include "include/pdf/fs_bookmark.h"
#include "include/pdf/fs_pdfdoc.h"
#include "include/pdf/fs_pdfpage.h"

using namespace foxit;
using namespace foxit::common;
using foxit::common::Library;
using namespace pdf;
...

// Assuming PDFDoc doc has been loaded.

Bookmark root = doc.GetRootBookmark();
Bookmark first_bookmark = root.GetFirstChild();

if (first_bookmark != null)
{
TraverseBookmark(first_bookmark, 0);
}

Private void TraverseBookmark(Bookmark root, int iLevel)
{
if (root != null)
{
              Bookmark child = root.GetFirstChild();
       while (child != null)
       {
          TraverseBookmark(child, iLevel + 1);
          child = child.GetNextSibling();
       }
        }
}
...
C
#include "include/fs_basictypes_c.h"
#include "include/fs_common_c.h"
#include "include/fs_filespec_c.h"
#include "include/fs_bookmark_c.h"
#include "include/fs_pdfdoc_c.h"
#include "include/fs_pdfpage_c.h"
...

// Assuming FS_PDFDOC_HANDLE doc has been loaded.

FS_BOOKMARK_HANDLE root;
FSDK_PDFDoc_GetRootBookmark(doc, &root);
FS_BOOKMARK_HANDLE first_bookmark;
FSDK_Bookmark_GetFirstChild(root, &first_bookmark);

if (first_bookmark != null)
{
TraverseBookmark(first_bookmark, 0);
}

Private void TraverseBookmark(FS_BOOKMARK_HANDLE root, int iLevel)
{
if (root != null)
{
                   FS_BOOKMARK_HANDLE child;
FSDK_Bookmark_GetFirstChild(root, &child);
    while (child != null)
       {
          TraverseBookmark(child, iLevel + 1);
          FSDK_Bookmark_GetNextSibling(child, &child);
       }
        }
}
...
java
import com.foxit.sdk.pdf.Bookmark;
import com.foxit.sdk.pdf.PDFDoc;
...

// Assuming PDFDoc doc has been loaded.
...

Bookmark root = doc.getRootBookmark();
if (root.isEmpty()) {
    root = doc.createRootBookmark();
}
            
String titleStr = "";
Bookmark iterBookmark = root.getFirstChild ();
if (iterBookmark.isEmpty())
    return;
while (!iterBookmark.isEmpty())
{
    titleStr = iterBookmark.getTitle();
    if (iterBookmark.hasChild())
    {
        Bookmark childBookmark = iterBookmark.getFirstChild();
        titleStr = childBookmark.getTitle();
    }
            	
    iterBookmark = iterBookmark.getNextSibling();
}
...
py
import sys
import site

if sys.version_info.major == 2:
    _PYTHON2_ = True
else:
    _PYTHON2_ = False

if _PYTHON2_:
    #replace with the python2 lib path
    site.addsitedir('../../../')
    from FoxitPDFSDKPython2 import *
else:
    from FoxitPDFSDKPython3 import *

...
# Assuming PDFDoc doc has been loaded.
root = doc.GetRootBookmark()
first_bookmark = root.GetFirstChild()

def TraverseBookmark(root, iLevel):
    if root is not None:
        child = root.GetFirstChild()
        while child is not None:    
            TraverseBookmark(child, iLevel + 1)
            child = child.GetNextSibling()

if first_bookmark is not None:
    TraverseBookmark(first_bookmark, 0)
...
objc
#include "FSPDFObjC.h"
...

// Assuming FSPDFDoc doc has been loaded.
...
FSBookmark *root = [doc getRootBookmark]; 
if (![root isEmpty]) {
    ShowBookmarkInfo(root, info, 0); 
}
void ShowBookmarkInfo(FSBookmark *bookmark, int depth) {
    if (depth > 32)
        return;
    if ([bookmark isEmpty]) {
        return;
    }
    ShowBookmarkInfo([bookmark getFirstChild], depth + 1);
    ShowBookmarkInfo([bookmark getNextSibling], depth);
}
...
js
const FSDK = require("@fuxinsoft/foxit-pdf-sdk-node");

...
// Assuming PDFDoc doc has been loaded.
let root = doc.GetRootBookmark();
let first_bookmark = root.GetFirstChild();

function TraverseBookmark(root, iLevel){
    if(!root.IsEmpty()) {
      let child = root.GetFirstChild()
      while(!child.IsEmpty()) {
        TraverseBookmark(child, iLevel + 1)
        child = child.GetNextSibling()
      }
    }
}
...
csharp
using foxit;
using foxit.common;
using foxit.common.fxcrt;
using foxit.pdf;
using foxit.pdf.actions;
...

//Assuming PDFDoc doc has been loaded.
...
Bookmark root = doc.GetRootBookmark();
Bookmark first_bookmark = root.GetFirstChild();
if (first_bookmark != null)
{
TraverseBookmark(first_bookmark, 0);
}

Private void TraverseBookmark(Bookmark root, int iLevel)
{
if (root != null)
{
              Bookmark child = root.GetFirstChild();
       while (child != null)
       {
          TraverseBookmark(child, iLevel + 1);
          child = child.GetNextSibling();
       }
        }
}
...
go
package main
import (
. “foxit.com/fsdk”
)

...
# Assuming PDFDoc doc has been loaded.
root := doc.GetRootBookmark()
first_bookmark := root.GetFirstChild()

func TraverseBookmark(root Bookmark, iLevel int){
    if !root .IsEmpty():
        child := root.GetFirstChild()
        for !child.IsEmpty(){   
            TraverseBookmark(child, iLevel + 1)
            child = child.GetNextSibling()
}
}
if first_bookmark != nil{
TraverseBookmark(first_bookmark, 0)
}
...

Add a new bookmark to the PDF document

c++
#include "include/common/fs_common.h"
#include "include/pdf/fs_filespec.h"
#include "include/pdf/fs_bookmark.h"
#include "include/pdf/fs_pdfdoc.h"
#include "include/pdf/fs_pdfpage.h"

using namespace std;
using namespace foxit;
using namespace foxit::common;
using foxit::common::Library;
using namespace pdf;

// Assuming PDFDoc doc has been loaded.

Bookmark root = doc.GetRootBookmark();
if (root.IsEmpty())
{
   root = doc.CreateRootBookmark();
}
Destination dest = Destination::CreateFitPage(doc, 0);
CFX_WideString ws_title;
ws_title.Format((FX_LPCWSTR)L"A bookmark to a page (index: %d)", 0);
Bookmark child = root.Insert(ws_title, foxit::pdf::Bookmark::e_PosLastChild);
child.SetDestination(dest);
child.SetColor(0xF68C21);
C
#include "include/fs_basictypes_c.h"
#include "include/fs_common_c.h"
#include "include/fs_filespec_c.h"
#include "include/fs_bookmark_c.h"
#include "include/fs_pdfdoc_c.h"
#include "include/fs_pdfpage_c.h"

int string2wstring(const char *source, size_t source_size, wchar_t *dest, size_t dest_size) {
  const char *_source;
  wchar_t *_dest;
  if (!source || !dest) return 0;
  _source = source;
  _dest = dest;
  setlocale(LC_ALL, "chs");
  mbstowcs(_dest, _source, _Dsize);
  setlocale(LC_ALL, "C");
  return (int)dest_size;
}

// Assuming FS_PDFDOC_HANDLE doc has been loaded.

FS_BOOKMARK_HANDLE root;
FSDK_PDFDoc_GetRootBookmark(doc, &root);
FS_BOOL return_value;
FSDK_Bookmark_IsEmpty(root, &return_value);
if (return_value)
{
   FSDK_PDFDoc_CreateRootBookmark(doc, &root);
}
FS_DESTINATION_HANDLE dest;
FSDK_Destination_CreateFitPage(doc, 0, &dest);
char str[128];
sprintf(str, "A bookmark to a page (index: %d)", i);
wchar_t ws_title[MAX_FILE_PATH];
FSErrorCode error_code;
string2wstring(path, MAX_FILE_PATH, ws_title, MAX_FILE_PATH);
FS_BOOKMARK_HANDLE child;
FSDK_Bookmark_Insert(root, ws_title, e_FSPosLastChild, &child);
FSDK_Bookmark_SetDestination(child, dest);
FSDK_Bookmark_SetColor(child, 0xF68C21);
java
import com.foxit.sdk.pdf.Bookmark;
import com.foxit.sdk.pdf.PDFDoc;
import com.foxit.sdk.pdf.actions.Destination;
import static com.foxit.sdk.pdf.Bookmark.e_PosLastChild;

// Assuming PDFDoc doc has been loaded.

Bookmark root = doc.getRootBookmark();
if (root.isEmpty()) {
    root = doc.createRootBookmark();
}
Destination dest = Destination.createFitPage(doc, 0);

String ws_title = String.format("A bookmark to a page (index: %d)", 0);
Bookmark child = root.insert(ws_title, e_PosLastChild);
child.setDestination(dest);
child.setColor(0xF68C21);
py
import sys
import site

if sys.version_info.major == 2:
    _PYTHON2_ = True
else:
    _PYTHON2_ = False

if _PYTHON2_:
    #replace with the python2 lib path
    site.addsitedir('../../../')
    from FoxitPDFSDKPython2 import *
else:
    from FoxitPDFSDKPython3 import *

# Assuming PDFDoc doc has been loaded.
root = doc.GetRootBookmark()
if root.IsEmpty():
    root = doc.CreateRootBookmark()

dest = Destination.CreateFitPage(doc, 0)
ws_title = str.format("A bookmark to a page (index: {})", 0)
child = root.Insert(ws_title, Bookmark.e_PosLastChild)
child.SetDestination(dest)
child.SetColor(0xF68C21)
objc
#include "FSPDFObjC.h"

// Assuming PDFDoc doc has been loaded.

FSBookmark *root = [doc getRootBookmark];
if ([root isEmpty]) {
    root = [doc createRootBookmark];
}
FSDestination *dest = [FSDestination createFitPage:doc page_index:0];
NSString *title = [NSString stringWithFormat:@"A bookmark to a page (index: %d)", 0];
FSBookmark *child = [root insert:title position:FSBookmarkPosLastChild];
[child setDestination:dest];
[child setColor:0xF68C21];
js
const FSDK = require("@fuxinsoft/foxit-pdf-sdk-node");

// Assuming PDFDoc doc has been loaded.
let root = doc.GetRootBookmark();
if (root.IsEmpty())
{
  root = doc.CreateRootBookmark();
}

let dest = FSDK.Destination.CreateFitPage(doc, i);
let ws_title = `A bookmark to a page (index: ${i})`;
let child = root.Insert(ws_title, FSDK.Bookmark.e_PosLastChild);
child.SetDestination(dest);
child.SetColor(i * 0xF68C21);
csharp
using foxit;
using foxit.common;
using foxit.common.fxcrt;
using foxit.pdf;
using foxit.pdf.actions;

// Assuming PDFDoc doc has been loaded.

Bookmark root = doc.GetRootBookmark();
if (root.IsEmpty())
{
    root = doc.CreateRootBookmark();
}
using (Destination dest = Destination.CreateFitPage(doc, 0))
{
    string ws_title = string.Format("A bookmark to a page (index: {0})", 0);

    Bookmark child;
    using (child = root.Insert(ws_title, Bookmark.Position.e_PosLastChild))
    {
        child.SetDestination(dest);
        child.SetColor(0xF68C21);
    }
}
go
package main
import (
. “foxit.com/fsdk”
“fmt”
)

# Assuming PDFDoc doc has been loaded.
root := doc.GetRootBookmark()
if root.IsEmpty(){
root = doc.CreateRootBookmark()
}

dest := DestinationCreateFitPage(doc, 0)
ws_title := fmt.Sprintf("A bookmark to a page (index: %d)", 0)
child := root.Insert(ws_title, BookmarkE_PosLastChild)
child.SetDestination(dest)
child.SetColor(uint(0xF68C21))
……
DeleteDestination(dest)

Create a table of contents based on PDF bookmark information

c++
#include "include/common/fs_common.h"
#include "include/pdf/fs_filespec.h"
#include "include/pdf/fs_bookmark.h"
#include "include/pdf/fs_pdfdoc.h"
#include "include/pdf/fs_pdfpage.h"

using namespace foxit;
using namespace foxit::common;
using foxit::common::Library;
using namespace pdf;
...

void AddTOCToPDF(PDFDoc doc) {
    /Set the table of contents configuration.
    Int32Array intarray;
    int depth = doc.GetBookmarkLevelDepth();
    if (depth > 0) {
        for (int i = 1; i <= depth; i++) {
            intarray.Add(i);
        }
    }
    WString title = L"";
    TableOfContentsConfig toc_config = TableOfContentsConfig(title, intarray, true, false);

    /Add the table of contents
    doc.AddTableOfContents(toc_config);
}
C
#include "include/fs_basictypes_c.h"
#include "include/fs_common_c.h"
#include "include/fs_filespec_c.h"
#include "include/fs_bookmark_c.h"
#include "include/fs_pdfdoc_c.h"
#include "include/fs_pdfpage_c.h"

void AddTOCToPDF(FS_PDFDOC_HANDLE& doc) {
    / Set the table of contents configuration.
    int depth = 0;
    FSDK_PDFDoc_GetBookmarkLevelDepth(doc, &depth);
    int* intarray = (int*)malloc(depth * sizeof(int));
    if (depth > 0) {
        for (int i = 1; i <= depth; i++) {
            intarray[i - 1] = i;
        }
    }
    FS_WSTR title;
    title.str = NULL;
    title.len = 0;
    FSTableOfContentsConfig toc_config;
    toc_config.bookmark_level_array = intarray;
    toc_config.bookmark_level_array_length = depth;
    toc_config.title = title;
    toc_config.is_show_serial_number = true;
    toc_config.include_toc_pages = false;

    / Add the table of contents.
    FSDK_PDFDoc_AddTableOfContents0(doc, toc_config);
    free(intarray);
}
java
import com.foxit.sdk.pdf.Bookmark;
import com.foxit.sdk.pdf.PDFDoc;
import com.foxit.sdk.pdf.actions.Destination;
import static com.foxit.sdk.pdf.Bookmark.e_PosLastChild;

static void AddTOCToPDF(PDFDoc doc) throws PDFException {
    Int32Array intarray = new Int32Array();
    int depth = doc.getBookmarkLevelDepth();
    if (depth > 0) {
      for (int i = 1; i <= depth; i++) {
          intarray.add(i);
      }
    }
    String title = "";
    TableOfContentsConfig toc_config = new TableOfContentsConfig(title, intarray, true, false);
 
    / Add the table of contents
    doc.addTableOfContents(toc_config);
}
py
import sys
import site

if sys.version_info.major == 2:
    _PYTHON2_ = True
else:
    _PYTHON2_ = False

if _PYTHON2_:
    #replace with the python2 lib path
    site.addsitedir('../../../')
    from FoxitPDFSDKPython2 import *
else:
    from FoxitPDFSDKPython3 import *
        
...
def AddTOCToPDF(doc):
    # Set the table of contents configuration.
    intarray = Int32Array()
    depth = doc.GetBookmarkLevelDepth()
    if depth > 0:
        for i in range(1, depth):
            intarray.Add(i)
            
    title = ""
    toc_config = TableOfContentsConfig(title, intarray, True, False)

    # Add the table of contents
doc.AddTableOfContents(toc_config)
objc
#include "FSPDFObjC.h"
...

void addTOCToPDF(FSPDFDoc* doc) {
    @autoreleasepool {
        / Set the table of contents configuration.
        FSInt32Array* intarray = [[FSInt32Array alloc] init];
        int depth = [doc getBookmarkLevelDepth];
        if (depth > 0) {
            for (int i = 1; i <= depth; i++) {
                [intarray add:i];
            }
        }
        NSString* title = @"";
        FSTableOfContentsConfig* toc_config = [[FSTableOfContentsConfig alloc] initWithTitle:title bookmark_level_array:intarray is_show_serial_number:true include_toc_pages:false];
 
        / Add the table of contents.
        [doc addTableOfContentsWithTableOfContentsConfig:toc_config];
    }
}
js
const FSDK = require("@fuxinsoft/foxit-pdf-sdk-node");
        
...
function AddTOCToPDF(doc){
  / Set the table of contents configuration.
  let name_array = new FSDK.Int32Array();
  depth = doc.GetBookmarkLevelDepth()
  if(depth > 0) {
    for(var i = 0; i < depth; i++) {
      name_array.Add(i);
    }
  }

  let title = ""
  let toc_config = new FSDK.TableOfContentsConfig(title, intarray, True, False)
}
// Add the table of contents
doc.AddTableOfContents(toc_config)
csharp
using foxit;
using foxit.common;
using foxit.common.fxcrt;
using foxit.pdf;
using foxit.pdf.actions;

static void AddTOCToPDF(PDFDoc doc)
{
    /Set the table of contents configuration.
    using (var intarray = new Int32Array())
    {
        int depth = doc.GetBookmarkLevelDepth();
        if (depth > 0)
        {
            for (int i = 1; i <= depth; i++)
            {
                intarray.Add(i);
            }
        }
        string title = "";
        using (var toc_config = new TableOfContentsConfig(title, intarray, true, false))
        {
            /Add the table of contents
            doc.AddTableOfContents(toc_config);
        }
    }
}
go
package main
import (
. “foxit.com/fsdk”
)        
...
func AddTOCToPDF(doc PDFDoc){
    # Set the table of contents configuration.
    intarray := NewInt32Array()
    depth := doc.GetBookmarkLevelDepth()
    if depth > 0{
        for i :=1; I < depth; i++{
            intarray.Add(i)
            }
}
    title := ""
toc_config := NewTableOfContentsConfig(title, intarray, true, false)
defer DeleteTableOfContentsConfig(toc_config)
    # Add the table of contents
doc.AddTableOfContents(toc_config)
}