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:
| Rule | Requirement |
|---|---|
6.8-2 | The file specification carries both F and UF file name entries. |
6.8-3 | It 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 msSample output
The same file checked with veraPDF:
