Documentation
¶
Overview ¶
Package dtd validates an XML document against the DTD in its internal subset.
It lives outside xdm because it needs the content-model automaton in xsd, and xdm is what xsd is built on — putting it there would invert the dependency. The split also keeps the parser's job clear: xdm reads a document and applies the two declarations whose absence is visible in the data model (attribute defaults and internal entities), while deciding whether the document *satisfies* its DTD is validation and belongs here.
Scope ¶
A DTD is a smaller language than XSD, and almost all of it maps onto machinery that already exists:
- <!ELEMENT> content models are a strict subset of what xsd's Glushkov automaton compiles — DTD has sequence, choice, and the ?, * and + quantifiers, and no numeric occurrence bounds at all.
- <!ATTLIST> required/implied/fixed maps onto attribute use.
- ID, IDREF and IDREFS are the same document-scoped uniqueness and reference checks XSD defines.
What DTD has that XSD does not is the *external* subset, which is a file reference. Fetching one is the attack AllowDOCTYPE exists to gate, so it is not read: a DOCTYPE naming an external subset validates against whatever its internal subset declares, and Validate says so rather than pretending the document was fully checked.
Index ¶
Constants ¶
const DefaultMaxErrors = 100
DefaultMaxErrors bounds how many failures are reported.
Variables ¶
This section is empty.
Functions ¶
func Validate ¶
Validate checks a document against the DTD in its own internal subset.
The DTD is read from the document rather than supplied separately, which is what a DOCTYPE means. A document with no DOCTYPE is valid trivially: there are no constraints to violate.
The document must have been parsed with xdm.ParseOptions.AllowDOCTYPE set, since without it the parse fails before this is reachable.
What is checked: element content models, attribute presence (#REQUIRED and #FIXED), enumerated attribute values, and ID/IDREF. What is not: anything declared in an *external* subset, which is not fetched — Validate reports that as a limitation rather than passing the document silently.
Types ¶
type AttrDefault ¶
type AttrDefault int
AttrDefault is how an attribute's presence is constrained.
const ( // AttrImplied is #IMPLIED: optional, no default. AttrImplied AttrDefault = iota // AttrRequired is #REQUIRED: must be present. AttrRequired // AttrFixed is #FIXED "v": if present the value must be v. AttrFixed // AttrDefaulted is a bare "v": supplied when absent. AttrDefaulted )
type Attribute ¶
type Attribute struct {
Element string
Name string
// Type is the declared type: CDATA, ID, IDREF, IDREFS, NMTOKEN,
// NMTOKENS, ENTITY, ENTITIES, NOTATION, or an enumeration.
Type string
// Enum holds the permitted values of an enumeration or NOTATION type.
Enum []string
Default AttrDefault
Value string
}
Attribute is one attribute definition within an <!ATTLIST>.
type ContentKind ¶
type ContentKind int
ContentKind is what an element's content model permits.
const ( // ContentEmpty is EMPTY: no child elements and no character data. ContentEmpty ContentKind = iota // ContentAny is ANY: anything, unchecked. ContentAny // ContentMixed is (#PCDATA | a | b)*: text interleaved with a set of // element names, in any order and any number. ContentMixed // ContentChildren is an element-only model such as (a, b*, (c|d)?). ContentChildren )
type DTD ¶
type DTD struct {
// Elements maps an element name to its content model.
Elements map[string]*Element
// Attributes maps an element name to its declared attributes.
Attributes map[string][]*Attribute
// HasExternalSubset records that the DOCTYPE named a SYSTEM or PUBLIC
// identifier. Nothing is fetched, so validation is against the internal
// subset alone and callers are told rather than misled.
HasExternalSubset bool
}
DTD is the subset of a document type declaration this package applies.
func Parse ¶
Parse reads the declarations out of a DOCTYPE's internal subset.
The argument is the directive text as encoding/xml hands it over — the whole "DOCTYPE name [...]" including the brackets. Anything the grammar here does not recognise is skipped rather than guessed at, so an unusual declaration leaves the document less constrained rather than wrongly rejected.
type Element ¶
type Element struct {
Name string
Kind ContentKind
// Mixed is the set of names a mixed model admits. Order and repetition
// are unconstrained there, so a set is the whole model.
Mixed map[string]bool
// Particle is the compiled model for ContentChildren, expressed in xsd's
// component model so that the existing automaton can run it.
Particle *xsd.Particle
}
Element is one <!ELEMENT> declaration.
type Error ¶
type Error struct {
// Path locates the element, as "/root/child".
Path string
// Message says what was wrong.
Message string
}
Error is one validity failure.
type Errors ¶
type Errors struct{ Errors []*Error }
Errors is what Validate returns when a document is not valid.
type Options ¶
type Options struct {
// MaxErrors stops after this many failures. Zero means
// DefaultMaxErrors; a negative value means no limit.
//
// A document wrong in every element would otherwise produce an error per
// element, which helps nobody and costs memory proportional to the input.
MaxErrors int
// AllowUndeclared skips elements the DTD says nothing about instead of
// reporting them.
//
// Strictly, an undeclared element is a validity error: a DTD is a closed
// description, unlike a schema where a wildcard may admit the unknown.
// But a document whose DOCTYPE names an *external* subset and declares
// only a few things internally is the common real-world shape — the
// W3C's own RFC 3986 type library declares one element and one attribute
// list, purely so that an external DTD's attributes work — and validating
// that against its internal subset alone reports every other element as
// undeclared, which is noise rather than a finding.
//
// Off by default, so the strict reading is what a caller gets unless they
// ask otherwise. Turn it on when the DTD is known to be partial;
// HasExternalSubset is how to detect that case.
AllowUndeclared bool
}
Options configures Validate.