Skip to main content

sup_xml_core/dtd/
model.rs

1//! Type-level DTD vocabulary — Element/Attribute decls and content models.
2
3/// An `<!ELEMENT name model>` declaration.
4#[derive(Debug, Clone)]
5pub struct ElementDecl {
6    pub name:    String,
7    pub content: ContentModel,
8}
9
10/// XML 1.0 § 3.2 element content classifications.
11#[derive(Debug, Clone)]
12pub enum ContentModel {
13    /// `EMPTY` — no children of any kind allowed.
14    Empty,
15    /// `ANY` — anything goes (no validation against this element).
16    Any,
17    /// Mixed content per § 3.2.2 [51].  Either `(#PCDATA)*` (no
18    /// child elements named, `choices` empty) or
19    /// `(#PCDATA | a | b ...)*`.  Always carries the trailing `*`
20    /// implicitly when `choices` is non-empty.
21    Mixed { choices: Vec<String> },
22    /// Children content per § 3.2.1 [47].  A nested group of
23    /// element-name particles with sequence/choice/occurrence
24    /// structure.
25    Children(Group),
26}
27
28/// One Sequence or Choice with its own occurrence indicator —
29/// matches the grammar in § 3.2.1 [49] / [50].
30#[derive(Debug, Clone)]
31pub struct Group {
32    pub kind:  GroupKind,
33    pub items: Vec<Particle>,
34    pub occur: Occurrence,
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum GroupKind { Sequence, Choice }
39
40/// One element-name reference or a nested Group, with its own
41/// `?` / `*` / `+` indicator.
42#[derive(Debug, Clone)]
43pub struct Particle {
44    pub item:  Item,
45    pub occur: Occurrence,
46}
47
48#[derive(Debug, Clone)]
49pub enum Item {
50    /// `Name` per [48] — refers to another element by GI.
51    Name(String),
52    /// Nested parenthesised group.
53    Group(Box<Group>),
54}
55
56/// `?` / `*` / `+` per § 3.2.1 [47].  `One` = no suffix.
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub enum Occurrence {
59    One,
60    ZeroOrOne,
61    ZeroOrMore,
62    OneOrMore,
63}
64
65/// A reference to one internal/external-subset declaration in source
66/// order, so the DTD serializer can reproduce libxml2's declaration
67/// ordering (it walks `xmlDtd.children`, which is source order).
68#[derive(Debug, Clone)]
69pub enum DeclRef {
70    /// `<!ELEMENT name …>` — index by name into `Dtd::elements`.
71    Element(String),
72    /// `<!ATTLIST name …>` — index by name into `Dtd::attlists`.
73    Attlist(String),
74    /// `<!ENTITY …>` — index into `Dtd::entities`.
75    Entity(usize),
76}
77
78/// An `<!ENTITY name ...>` general-entity declaration — internal (with a
79/// literal replacement text) or external (SYSTEM/PUBLIC, optionally
80/// `NDATA`).  Mirrors the fields lxml reads off libxml2's `xmlEntity`
81/// and what the DTD serializer reconstructs.
82#[derive(Debug, Clone)]
83pub struct EntityDecl {
84    pub name: String,
85    /// `true` for a parameter entity (`<!ENTITY % name …>`).
86    pub parameter: bool,
87    /// Replacement text as written, before reference expansion
88    /// (libxml2's `orig`).  `None` for external entities.
89    pub orig: Option<String>,
90    /// Replacement text after character/entity-reference expansion
91    /// (libxml2's `content`).  `None` for external entities.
92    pub content: Option<String>,
93    /// `SYSTEM` identifier (or the second literal of `PUBLIC`).
94    pub system_id: Option<String>,
95    /// `PUBLIC` identifier.
96    pub public_id: Option<String>,
97    /// `NDATA` notation name — present only for unparsed entities.
98    pub ndata: Option<String>,
99}
100
101/// One row of an `<!ATTLIST element name type default>` block.
102#[derive(Debug, Clone)]
103pub struct AttDecl {
104    pub name:    String,
105    pub att_type: AttType,
106    pub default:  AttDefault,
107}
108
109/// XML 1.0 § 3.3.1 attribute types.
110#[derive(Debug, Clone)]
111pub enum AttType {
112    CData,
113    Id,
114    IdRef,
115    IdRefs,
116    Entity,
117    Entities,
118    Nmtoken,
119    Nmtokens,
120    /// `NOTATION (n1 | n2 | ...)`.  Stored verbatim for completeness;
121    /// the validator does not currently cross-check against `<!NOTATION>`
122    /// declarations.
123    Notation(Vec<String>),
124    /// `(v1 | v2 | ...)` — enumerated.  The attribute value at the
125    /// document body must match one of these literally.
126    Enumeration(Vec<String>),
127}
128
129/// XML 1.0 § 3.3.2 default declarations.
130#[derive(Debug, Clone)]
131pub enum AttDefault {
132    /// `#REQUIRED`
133    Required,
134    /// `#IMPLIED`
135    Implied,
136    /// `#FIXED "value"` — attribute must equal `value` if present.
137    Fixed(String),
138    /// Literal default value — supplied if the attribute is absent
139    /// from the document body.  v0.1 doesn't perform defaulting at
140    /// parse time, so the validator just ignores this and accepts
141    /// either presence or absence.
142    Default(String),
143}