Documentation
¶
Overview ¶
Package xfa reads Adobe's XML Forms Architecture — the form description carried inside a PDF whose pages are a placeholder.
Why this exists ¶
A PDF form comes in two kinds, and only one of them is a PDF form. Measured over 2 240 real government forms: 560 carry an XFA package, and 546 of those are STATIC — a second, proprietary description of a form that is already drawn on the pages, which go-pdfkit/forms reads and fills without help.
The other fourteen are DYNAMIC. Their pages hold a panel reading "Please wait... your PDF viewer may not be able to display this type of document", and the form exists only as XML, laid out when the document is opened. Adobe removed the format from PDF 2.0; no browser and no other reader lays one out. A person handed such a file has a document that looks blank and is not.
What it does, and what it will not ¶
This reads the template — the description of the form — into a typed tree, and the datasets, which hold what has been filled in. It does not run the forms' scripts, and that is a measured decision rather than a shortcut: of 5 744 scripts across those fourteen forms, 5 131 are handlers for enter, exit, change and click. They fire when somebody types. Only 188 run at load, so the form a reader first sees does not depend on them.
FormCalc, XFA's other scripting language, is not read either: every script in the corpus declares itself as JavaScript.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Measure ¶
type Measure float64
A Measure is a length, in points.
XFA writes lengths as a number and a unit — "62mm", "9pt", "0.25in" — and mixes them freely within one form: the corpus's simplest template gives its page in points, its content area's origin in inches and its fields' widths in millimetres, all in the same subform.
func ParseMeasure ¶
ParseMeasure reads a length. A bare number is points, which is what the specification says and what the corpus writes for a page's height.
type Node ¶
type Node struct {
// Kind is the element's name, without its namespace: "subform", "field",
// "draw", "pageArea".
Kind string
// Attr are its attributes, by name without namespace.
Attr map[string]string
// Text is the character data directly inside it, with surrounding space
// trimmed. A <text> element's caption lives here.
Text string
// Kids are the elements inside it, in order. Order is not decoration: a
// subform laid out top-to-bottom places its children in it.
Kids []*Node
}
A Node is one element of a template, with the children it contains.
The tree is kept whole rather than reduced to the elements this package understands today. XFA has some hundreds of element types and a form uses a few dozen; throwing the rest away at parse time would mean re-parsing to add each one, and would lose the ordering that layout depends on.
func ParseTemplate ¶
ParseTemplate reads the template part of an XFA package.
It is lenient in one direction and strict in the other. Namespaces are dropped, because a template writes the same element under xfa-template and under no namespace at all depending on who produced it, and the difference carries nothing. Processing instructions and comments are skipped: a template written by Adobe's designer carries hundreds of them recording what the designer did, which is not part of the form.
A document whose XML does not close is refused. Half a template is not a form, and laying one out would put half a form on paper without saying so.
func (*Node) Child ¶
Child is the first child of that kind, or nil. Most of the template is singular — a field has one ui, one border, one caption — so looking one up by name is how it is read.