Available starting from PD4ML v4.1.1

Export a PDF's annotations and form field values to an XFDF file, or import an XFDF file's annotations/field values back into a PDF - no code to write.

Main-Class com.pd4ml.pdf.xfdf.cli.Pd4XfdfCli Modes export, import

1. Invocation

java -cp pd4ml.jar com.pd4ml.pdf.xfdf.cli.Pd4XfdfCli <export|import> [flags...]

Throughout this document, pd4ml.jar stands for the pd4ml library jar (present in the current directory in every example below) - com.pd4ml.pdf.xfdf.cli.Pd4XfdfCli isn't pd4ml.jar's own Main-Class (that's com.pd4ml.tools.Pd4Cmd, a different tool), so invoke it with -cp, not -jar. Running with no arguments, or help/--help/-h as the first argument, prints the same usage summary this page expands on.

Two modes, given as the first positional argument: export and import. All flags use --key=value syntax; a flag with no =value (--update-if-exists, --optimize) is a boolean switch, true by its mere presence. There is no short-flag form.

Exit codes

0

Success.

1

The operation failed for a business/runtime reason - bad password, malformed PDF/XFDF… The message on stderr explains why.

2

Usage error - missing/invalid mode or flags. Usage text is printed to stderr alongside the message.

↑ Back to top

2. export PDF -> XFDF

pd4xfdfcli export --in=<file.pdf> [--password=<pw>] --out=<output.xfdf> [--types=<csv>] [--ids=<csv>]
--in=<file.pdf>
required
--password=<pw>
if the input is encrypted (tried as user and owner password; omit for an empty password)
--out=<output.xfdf>
required
--types=<csv>
restrict to these annotation XFDF element names and/or field /FT codes - see §4
--ids=<csv>
restrict to these annotation /NM values and/or fully-qualified field names - see §4

Examples

Export everything:

$ java -cp pd4ml.jar com.pd4ml.pdf.xfdf.cli.Pd4XfdfCli export --in=reviewed.pdf --out=comments.xfdf
Exported reviewed.pdf -> comments.xfdf (1254 bytes)

Export only highlights:

$ java -cp pd4ml.jar com.pd4ml.pdf.xfdf.cli.Pd4XfdfCli export --in=reviewed.pdf --out=highlights.xfdf --types=highlight

Export from an encrypted PDF:

$ java -cp pd4ml.jar com.pd4ml.pdf.xfdf.cli.Pd4XfdfCli export --in=protected.pdf --password=secret --out=comments.xfdf
↑ Back to top

3. import XFDF -> PDF

pd4xfdfcli import --in=<file.pdf> [--password=<pw>] --xfdf=<input.xfdf> --out=<output.pdf> [--update-if-exists] [--types=<csv>] [--ids=<csv>] [--optimize] [--encrypt-user=<pw>] [--encrypt-owner=<pw>] [--encrypt-alg=RC4_128|AES_128|AES_256] [--permissions=<int>]

Input/output

--in=<file.pdf>
required
--password=<pw>
if the input is encrypted
--xfdf=<input.xfdf>
required
--out=<output.pdf>
required

Matching behavior

--update-if-exists
an <annots> entry whose name matches an annotation already in the PDF updates it in place instead of adding a duplicate; default: always add (see the PD4ML XFDF Manual's §4)
--types=<csv>
apply only these annotation types and/or field /FT codes - see §4
--ids=<csv>
apply only these annotation IDs and/or field names - see §4

<fields> entries always only update an existing AcroForm field, regardless of --update-if-exists - see the manual's §5.

Post-processing optional

--optimize
run the same reachability/dedup cleanup as pd4optimizecli on the imported PDF before it's written
--encrypt-user=<pw>
open (user) password for the imported output
--encrypt-owner=<pw>
owner password for the imported output
--encrypt-alg=RC4_128|AES_128|AES_256
default AES_256 when any encrypt-* flag is given
--permissions=<int>
raw /P permission bits (ISO 32000-1 Table 22); default "everything allowed"

If both --optimize and an --encrypt-* flag are given, optimization always runs first and encryption is applied to its result (see the manual's §6.2).

Examples

Add every annotation/field value from an XFDF file:

$ java -cp pd4ml.jar com.pd4ml.pdf.xfdf.cli.Pd4XfdfCli import --in=original.pdf --xfdf=comments.xfdf --out=annotated.pdf
Imported comments.xfdf into original.pdf -> annotated.pdf (6 annotation(s) added, 0 updated, 2 field(s) updated)

Re-import a revised XFDF, updating matching annotations in place:

$ java -cp pd4ml.jar com.pd4ml.pdf.xfdf.cli.Pd4XfdfCli import --in=annotated.pdf --xfdf=comments-revised.xfdf --out=merged.pdf --update-if-exists

Import only checkbox/radio field values, skipping everything else in the file:

$ java -cp pd4ml.jar com.pd4ml.pdf.xfdf.cli.Pd4XfdfCli import --in=form.pdf --xfdf=answers.xfdf --out=filled.pdf --types=btn

Import, clean up, and lock the result:

$ java -cp pd4ml.jar com.pd4ml.pdf.xfdf.cli.Pd4XfdfCli import \
      --in=form.pdf --xfdf=answers.xfdf --out=filled-locked.pdf \
      --optimize --encrypt-user=open123 --encrypt-owner=owner456 --encrypt-alg=AES_256

A successful run reports what it did, including any field names that matched nothing:

Imported answers.xfdf into form.pdf -> filled.pdf (0 annotation(s) added, 0 updated, 2 field(s) updated, 1 field(s) not found)
Fields not found: bonus.signature
↑ Back to top

4. --types / --ids grammar

Both flags take a comma-separated list and are shared, unchanged, between export and import - see the PD4ML XFDF Manual's §6.1 for the full matching rules. In short: --types matches an annotation's lower-case XFDF element name (square, freetext, ...) or a field's PDF /FT code (Tx/Btn/Ch, case-insensitive) - the two vocabularies never overlap, so --types=square,tx selects Square annotations and text fields at once. --ids matches an annotation's exact /NM or a field's exact fully-qualified name.

↑ Back to top

5. Troubleshooting

"is encrypted and the given password (or no password) did not open it"

Add --password=<pw> (either the input's user or owner password authenticates), or double-check the one given.

"Not an XFDF document (root element is not <xfdf>)" / "Malformed XFDF XML"

The --xfdf file isn't well-formed XML, or its root element isn't <xfdf> - check it opens cleanly in a text editor and starts with an <xfdf xmlns="http://ns.adobe.com/xfdf/"> root.

A field is listed under "Fields not found" even though it "obviously" exists

Either the name in the XFDF doesn't exactly match the field's fully-qualified (dot-joined) name in the target PDF's /AcroForm (case-sensitive), the field is a /FT /Sig signature field (never touched - see the manual's §5), or it was excluded by --types/--ids (which is reported this same way, not separately - see §4).

An updated annotation/field doesn't look different in my viewer

Import never regenerates /AP appearance streams (see the manual's §4) - the new value is correct in the PDF immediately, but most viewers only re-render it the next time they regenerate appearances (typically on open).

Structural editing, merging, or general COS work

pd4xfdfcli only handles annotations and form field values; for combining page ranges from several PDFs, see the pd4mergecli Reference (com.pd4ml.pdf.merge.cli.Pd4MergeCli). For arbitrary dictionary/array edits or COS-path queries, see the pd4coscli Reference (com.pd4ml.pdf.cos.cli.CosCli). For reachability/duplicate-content cleanup on its own, see the pd4optimizecli Reference (com.pd4ml.pdf.optimizer.cli.Pd4OptimizeCli).

↑ Back to top

6. See also

↑ Back to top
PD4ML XFDF CLI · Java 1.8 · com.pd4ml.pdf.xfdf.cli.Pd4XfdfCli · no third-party PDF dependency