PureXML/Sources/Validation/AttributeType.swift
Mihaela Mihaljevic 7f1aada240 feat(dtd): conditional sections, notations, NDATA, external parameter entities
Deepen DTD processing in the doctype scanner:

- Conditional sections are processed, not skipped: INCLUDE sections have
  their declarations scanned, IGNORE sections are discarded, the keyword
  may be a parameter-entity reference, and nested sections are handled.
- <!NOTATION> declarations are parsed and stored on DocumentType.
- Unparsed entities (<!ENTITY ... NDATA n>) are parsed and stored with
  their notation, distinct from general entities.
- External parameter entities are loaded through the injected resolver so
  their declarations expand; the default refusing resolver loads nothing,
  keeping XXE closed.
- NOTATION attributes are a distinct type, validated against the declared
  notations (value must be listed and the notation declared).

Tracking unparsed entities also lets ENTITY/ENTITIES attribute values be
validated against the declared NDATA entities, closing the gap left when
#73 could only check name syntax.

Closes #72
2026-06-08 14:39:42 +02:00

28 lines
1.2 KiB
Swift

extension PureXML.Validation {
/// The declared type of a DTD attribute. An enumeration constrains the value to
/// a fixed set; the tokenized types constrain its lexical form (a name token, a
/// name); and the ID family drives cross-document uniqueness and reference
/// checks.
enum AttributeType: Equatable {
case cdata
case enumeration([String])
/// `NOTATION (a|b)`: the value must be one of the listed notation names,
/// each of which must be a declared `<!NOTATION>`.
case notation([String])
/// `ID`: the value must be unique across the document.
case id
/// `IDREF`: the value must match some declared `ID`.
case idReference
/// `IDREFS`: each whitespace-separated value must match some declared `ID`.
case idReferences
/// `NMTOKEN`: the value must be a single XML name token.
case nmToken
/// `NMTOKENS`: each whitespace-separated value must be a name token.
case nmTokens
/// `ENTITY`: the value must be an XML name (naming an unparsed entity).
case entity
/// `ENTITIES`: each whitespace-separated value must be a name.
case entities
}
}