Skip to content
Validate PDF/A-3 Standard

Validate PDF/A-3 Standard

Validation checks a file against a profile and returns the rules it breaks. It needs a CompliancePdfReader, which parses in compliance mode and keeps the byte-level detail the header, trailer and cross-reference rules depend on. A plain PdfReader will not type-check against ValidateStandard.

Part 3 runs the same rule set as PDF/A-2 with one difference, in the embedded file check. That difference is the reason to validate against part 3 rather than part 2.

Doing it

detailedReader, err := model.NewCompliancePdfReader(inputFile)
if err != nil {
    return err
}

for _, profile := range []model.StandardImplementer{
    pdfa.NewProfile3A(nil),
    pdfa.NewProfile3B(nil),
    pdfa.NewProfile3U(nil),
} {
    if err := profile.ValidateStandard(detailedReader); err != nil {
        fmt.Printf("%s: %v\n", profile.StandardName(), err)
    }
}

nil means nothing was found. Anything else is a pdfa.VerificationError holding a ViolatedRule per failed check, with the ISO clause number in RuleNo and the requirement text in Detail, sorted by clause.

The embedded file rules

Two rules are checked on every file specification that has an EF entry, and both are the same in parts 2 and 3:

RuleRequirement
6.8-2The file specification carries both F and UF file name entries.
6.8-3It carries an AFRelationship entry saying how the attachment relates to the document.

Part 2 adds a third, 6.8-4, requiring the embedded stream’s MIME type to be application/pdf. Part 3 does not run it. If a document with an XML or spreadsheet attachment fails part 2 validation on 6.8-4 and nothing else, it is a valid PDF/A-3 file and the part is what needs changing, not the document.

Both checks stop at the first violation, so a document with several malformed attachments reports one rule rather than one per attachment.

Reading the result

Running all three profiles over one file, as the example does, gives output that needs the conformance hierarchy to make sense. The pdfaid:conformance comparison accepts a level at least as strict as the one being tested, so a valid 3B file passes the 3B check and reports rule 6.6.4-3 for 3U and 3A. That is expected.

The levels also differ in what else runs. 3U and 3A require every composite font to carry a usable ToUnicode CMap unless it is a Type 1 font, reporting 6.2.11.7-1 otherwise. 3A additionally runs the logical structure checks, which want MarkInfo Marked set to true, a StructTreeRoot in the catalog, and non-standard structure types mapped in the role map.

Limitations

Validation is not complete, and the package documents itself as experimental. Several clauses exist in the source as unimplemented placeholders, including parts of the object syntax checks, the rendering intent check, the check that embedded font programs are one of the permitted formats, the Lang identifier check and the page PresSteps check. Nothing validates the attachment itself: an XML payload that does not match its invoice schema is not a PDF/A concern and will not be reported here. Use veraPDF as the oracle for a conformance claim, and the relevant invoice validator for the payload.

Run the example

pdfa3_validate_standard.go opens a file with NewCompliancePdfReader, then loops over a slice of model.StandardImplementer holding all three part 3 profiles and prints the violations for each.

git clone https://github.com/unidoc/unipdf-examples.git
cd unipdf-examples/pdfa
go run pdfa3_validate_standard.go <input.pdf>

If this is your first time using UniPDF, follow the getting started guide to create an API key and set up your development environment.

View the full source
Processing time: 7.64 ms

Sample output

The same file checked with veraPDF:

veraPDF report showing the file passing PDF/A-3 validation

Last updated on