Merging documents with bookmarks

This is a code example of iText PDF, discover more.

11th October 2015

Switch code for this example
 * Example written by Bruno Lowagie in answer to a question on StackOverflow
 * When concatenating documents, we add a named destination every time
 * a new document is started. After we've finished merging, we add an extra
 * page with the table of contents and links to the named destinations.
package sandbox.merge;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import sandbox.WrapToTest;

public class MergeWithOutlines {

    public static final String SRC1 = "resources/pdfs/hello.pdf";
    public static final String SRC2 = "resources/pdfs/links1.pdf";
    public static final String SRC3 = "resources/pdfs/links2.pdf";
    public static final String DEST = "results/merge/merge_with_outlines.pdf";
    public Map filesToMerge;
    public static void main(String[] args) throws IOException, DocumentException {
        File file = new File(DEST);
        new MergeWithOutlines().createPdf(DEST);
    public void createPdf(String filename) throws IOException, DocumentException {
        Document document = new Document();
        PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename));;
        int page = 1;
        ArrayList> outlines = new ArrayList>();
        // add the first document
        PdfReader reader1 = new PdfReader(SRC1);
        // add the first outline element
        HashMap helloworld = new HashMap();
        helloworld.put("Title", "Hello World");
        helloworld.put("Action", "GoTo");
        helloworld.put("Page", String.format("%d Fit", page));
        // update page count
        page += reader1.getNumberOfPages();
        // add the second document
        PdfReader reader2 = new PdfReader(SRC2);
        // add the second outline element as a kid of the first one
        ArrayList> kids = new ArrayList>();
        HashMap link1 = new HashMap();
        link1.put("Title", "link1");
        link1.put("Action", "GoTo");
        link1.put("Page", String.format("%d Fit", page));
        helloworld.put("Kids", kids);
        // update page count
        page += reader2.getNumberOfPages();
        // add the third document
        PdfReader reader3 = new PdfReader(SRC3);
        // add the third outline element to the root
        HashMap link2 = new HashMap();
        link2.put("Title", "Link 2");
        link2.put("Action", "GoTo");
        link2.put("Page", String.format("%d Fit", page));
        // add the outlines
        // close the document
 * Example written in answer to:
package sandbox.merge;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.SimpleBookmark;
import java.util.HashMap;
import java.util.List;
import sandbox.WrapToTest;

public class InsertAndAdaptOutlines {

    /** The original PDF file. */
    public static final String INSERT
        = "resources/pdfs/hello.pdf";
    /** The original PDF file. */
    public static final String SRC
        = "resources/pdfs/bookmarks.pdf";
    /** The resulting PDF file. */
    public static final String DEST
        = "results/merge/bookmarks_hello.pdf";
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
    public static void main(String[] args)
        throws IOException, DocumentException {
        File file = new File(DEST);
        new InsertAndAdaptOutlines().manipulatePdf(SRC, DEST);
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException {
        PdfReader insert = new PdfReader(INSERT);
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(DEST));
        stamper.insertPage(4, insert.getPageSize(1));
        PdfContentByte cb = stamper.getOverContent(4);
        cb.addTemplate(stamper.getImportedPage(insert, 1), 0, 0);
        List> outlines = SimpleBookmark.getBookmark(reader);
        HashMap entry = new HashMap();
        entry.put("Title", "Hello");
        entry.put("Action", "GoTo");
        entry.put("Page", "4 Fit");
        updateOutline(outlines, entry, 4);
    public boolean updateOutline(List> outlines, HashMap entry, int p) {
        int index = 0;
        for (HashMap outline : outlines) {
            Object kids = outline.get("Kids");
            if (kids != null) {
                updateOutline((List>)kids, entry, p);
            else {
                if (p < getPage(outline)) {
                    outlines.add(index, entry);
                    return true;
        return false;
    public int getPage(HashMap outline) {
        Object page = outline.get("Page");
        if (page == null) return -1;
        String p = page.toString().substring(0, page.toString().indexOf(" "));
        return Integer.parseInt(p);

Still have questions? 

We're happy to answer your questions. Reach out to us and we'll get back to you shortly.

Contact us
Stay updated

Join 11,000+ subscribers and become an iText PDF expert by staying up to date with our new products, updates, tips, technical solutions and happenings.

Subscribe Now