JPedal provides a parser and validator for the Arlington PDF Model
How to use the validator
You will need a copy of the Arlington PDF Model in TSV format, which you can find on the PDF Association’s GitHub repo: https://github.com/pdf-association/arlington-pdf-model. Clone/download the repo and note the location of the tsv/latest directory.
Command line
The command line application allows you to validate one or more files against the model. You may specify a level filter to only show validation issues of a specific or worse severity.
java org.jpedal.arlington.validate.PdfArlingtonValidator --tsv <path-to-arlington-tsv-dir> [--level LEVEL] file1.pdf [file2.pdf ...]
All issues are printed in the following format: [level] path-in-pdf (arlington-object-definition): issue-message.
Example output:
[ERROR] Trailer/Root/Pages/Kids[0]/Resources/Font/F1/Encoding/Type (Encoding): Value of 'Type' (/Font) is not one of the permitted values [Encoding]
[ERROR] Trailer/Root/Pages/Kids[0]/Resources/Font/F1/Widths (FontType3): SpecialCase constraint violated: fn:Eval((fn:ArrayLength(Widths) == (1.0 + (@LastChar - @FirstChar))))
[ERROR] Trailer/Root/Pages/Kids[0]/Resources/Font/F2/FontDescriptor (FontCIDType0): Value must be an indirect reference (fn:MustBeIndirect) but is a direct object
[ERROR] Trailer/Root/Pages/Kids[0]/Resources/Font/F2/FontDescriptor/Style/Panose (StyleDict): SpecialCase constraint violated: fn:Eval((fn:StringLength(Panose) == 12.0))
[ERROR] Trailer/Root/Pages/Kids[0]/Resources/Font/F2/FontDescriptor/Descent (FontDescriptorCIDType0): Value of 'Descent' (123) is not one of the permitted values [fn:Eval((@Descent <= 0.0))]
[ERROR] Trailer/Root/PageLayout (Catalog): Value of 'PageLayout' (/AnUndefinedOption) is not one of the permitted values [SinglePage, OneColumn, TwoColumnLeft, TwoColumnRight, TwoPageLeft, TwoPageRight]
[INFO] Trailer/Root/CatalogCustomKey (Catalog): Key 'CatalogCustomKey' is not defined by the Arlington model for Catalog and no wildcard entry is present
[ERROR] Trailer/Root/MarkInfo/Suspects (MarkInfo): Value has type integer but the model expects one of boolean for key/index 'Suspects'
[ERROR] Trailer/Root/Lang (Catalog): Value has type name but the model expects one of string-text for key/index 'Lang'
[WARNING] Trailer/Root/OpenAction/URI (ActionURI): Value of 'URI' ((\003\006Bad ASCII)) contains unprintable ASCII characters
Java
The Java methods allow you to validate one or more files against the model. You may also load password-protected/encrypted files.
// Load model
final Map<String, ArlingtonObject> model = ArlingtonModelLoader.load(Path.of("tsv/latest"));
// Load file
final PdfArlingtonValidator.Result result = validateFile(new File("inputFile.pdf"), model);
// Load file with password
final PdfArlingtonValidator.Result result = validateFile(new File("inputFile.pdf"), "password".getBytes(), model);
Any issues are returned as a list which you can then iterate over and inspect.
Example output:
for (final ValidationIssue issue : result.issues) {
// Iterate over issues
}