STXT Schema
1. Introduction
This document is STXT-SCHEMA-SPEC; the other specifications cite it by that name.
This document defines the specification of the STXT Schema language, a mechanism for validating STXT documents through formal semantic rules.
A schema:
- Is an STXT document with namespace
@stxt.schema. - Defines the nodes, types, and cardinalities of the target namespace.
- Does not modify the base syntax of STXT; it operates on the already parsed structure.
This document defines what a schema is and how it validates. The way a tool
locates schemas on the file system (.stxt directories, user and system
levels, STXT_PATH) is defined in STXT-DISCOVERY-SPEC.
1.1 Version of this specification
This specification carries its own date and its own status in the Last modif and
Status fields of its Metadata, independent of the other STXT specifications' and with
the meaning fixed by STXT-SPEC §1.1. It is in Aurora.
It depends on STXT-SPEC: a schema is an STXT document.
2. Terminology
The keywords "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" must be interpreted according to RFC 2119 and RFC 8174: they carry that meaning only when they appear in uppercase, as here.
Terms such as node, indentation, namespace, inline and >> block retain their meaning in STXT-SPEC.
3. Relationship between STXT and Schema
Schema validation occurs after STXT parsing:
- Parsing the document into a hierarchical STXT structure.
- Resolving the effective namespace of each node.
- Applying the corresponding schema.
An implementation MAY apply validation during the parsing process, provided that such validation remains loosely coupled to the base parser. This allows errors to be detected before the full parsing is completed.
4. General Structure of a Schema
A schema document MUST have as its root node:
Schema (@stxt.schema): <target_namespace>
Rules:
<target_namespace>MUST be a valid namespace according to STXT-SPEC.- The root node
SchemaMUST belong to the@stxt.schemanamespace. - The schema document MAY include a
Descriptionnode. - The schema document MUST include one or more
Nodenodes. - A schema document is exactly one
Schemanode: neither more than one root node, nor none (section 13, condition 12).
Example:
Schema (@stxt.schema): com.example.docs
Description: Example schema
Node: Document
Type: GROUP
Children:
Child: Author
Child: Date
Max: 1
Child: Content
Min: 1
Max: 1
Child: Metadata (org.example.meta)
Max: 1
Node: Author
Node: Date
Type: DATE
Node: Content
Type: TEXT5. One schema per namespace
For each logical namespace:
- There MUST NOT be more than one effective schema simultaneously.
- If an implementation has several candidate schemas for the same namespace, the choice is fixed by STXT-DISCOVERY-SPEC: the level closest to the document wins, and two definitions of the same namespace at the same level leave that namespace with no active definition.
- For a specific validation, there MUST be only one effective schema.
The empty namespace is not validated. A node whose effective namespace is "" (that of
everything that neither declares nor inherits a namespace, STXT-SPEC §7)
is valid by definition: a validator MUST NOT look up a schema for it nor emit
SCHEMA_NOT_FOUND for it. Since children inherit the namespace, a document without a
namespace stays entirely outside validation; a node that declares a namespace inside it is
validated, against the schema of that namespace. Consequently, no schema or template MAY
have "" as its target namespace: nothing could ever resolve against it.
6. Closed content model
STXT Schema uses a closed content model. This means that, for each node in the document, only the direct children explicitly declared in the schema are allowed.
Rules:
- If a
Nodedeclares aChildrenblock, its instances in the document MAY ONLY have as direct children the nodes declared throughChild(each identified by its logical paircanonical name + effective namespace). - If a
Nodedoes not declareChildren, its instances in the document MUST NOT have any direct children (total closure). - The appearance of an undeclared direct child MUST cause a validation error.
Any Node can be the root of a document. The schema does not distinguish between
"root" nodes and "child" nodes: a document whose root node is any Node of the namespace is
valid if that node satisfies its rules. So, against the schema of section 15.5,
both Document (com.example.docs): … and Title (com.example.docs): … are valid roots.
This allows partial documents (a fragment, one file per section) without extra schemas; a
schema that wants to restrict the root does so by convention, not by declaration.
This model is consistent with the STXT philosophy of failing loudly: a misspelled
node (for example Titel instead of Title) is detected as an undeclared child instead
of being silently accepted.
Note on evolution. A schema admits compatible extensions —adding a Child with a
minimum cardinality of zero, lowering a Min, raising a Max: changes that allow more
cases, not fewer— without any existing document ceasing to validate. The nuance is that
compatibility is relative to the extended definition: a document that uses the addition
does not validate against an earlier copy of the schema, so if the consumers of the
namespace do not update their copy at the same time, the same document may validate in one
and fail in another. Whether an extension needs a new version therefore depends on the use
case: on how the definition is distributed, not only on the change. For those situations,
and always for incompatible changes —a new mandatory Child, removing one, narrowing a
cardinality—, the recommended practice is to version the namespace in the namespace
itself (for example com.example.docs.v1 → com.example.docs.v2), so that each version
has its schema and documents declare the version they use.
Unresolved cross-namespace nodes. Declaring a Child that points to another namespace
does not require having the schema of that namespace: loading a schema never looks
inside other schemas, so the result is independent of load order.
The check happens when validating a document: if a node of that namespace appears,
its schema MUST be available and the node MUST exist in it as a Node:; otherwise,
the document is invalid. A cross-namespace child that is declared but never used
poses no problem (see section 8.1).
7. Node Definition (Node:)
7.1 Basic form
Node: Node Name
Description: Node description
Type: INLINE
Children:
Child: Child Name (another.namespace)
Min: 1
Max: 1Rules:
- The inline value of
NodeMUST be a valid node name according to STXT-SPEC. - Matching between a
Nodeand the nodes of the document is done by canonical name (STXT-SPEC §6):Node: Node Namevalidatesnode-name,NODE_NAMEandNode Name, and the same holds forChild. - Each
NodeMUST be unique within the schema at the canonical name level. - Each
Nodedefines the semantics of the node in the schema's target namespace. - If
Typeis omitted, the default type isINLINE. - A
NodeMUST NOT contain more than oneDescriptionnode, more than oneTypenode, more than oneChildrennode, nor more than oneValuesnode. - Only types that allow children (see section 9) MAY declare
Children. DeclaringChildrenin a type that does not allow children MUST cause a schema error. - The name of a
ChildMAY include a namespace when the child belongs to another namespace (section 8). MinandMaxare optional within aChild(section 10).
7.2 Values in ENUM types
Node: Node Name
Description: Node description
Type: ENUM
Values:
Value: value 1
Value: value 2
Value: value 3The ENUM type, and only ENUM, MAY specify a Values node with the allowed values through Value nodes.
If Values exists, it MUST contain at least one Value node.
If a Node declares Type: ENUM, it MUST include Values.
Each Value MUST have a non-empty inline value after trimming: an empty Value: MUST cause a schema error (VALUE_EMPTY), because an enumeration whose only valid value is the empty string makes no sense. For the same reason a Child: without a value is an error (INVALID_NODE_NAME, section 13.1).
Since ENUM does not allow children (section 9), a Node of type ENUM MUST NOT declare Children.
8. Children (Children:) and cross-namespaces
A node MAY have a Children entry.
If Children exists, it MUST contain one or more Child nodes with the information of the allowed children.
A Child MAY belong to another namespace, in which case it is indicated in the name of the Child itself.
Example:
- If the namespace is omitted, the
Childbelongs to the target namespace of the current schema. - If an explicit namespace is indicated, the
Childbelongs to that specific namespace. - Within the same
Childrennode, an implementation MUST NOT accept twoChildnodes that point to the same logical paircanonical name + effective namespace.
8.1 Explicitly defined nodes
Every node that appears in Children must have its own definition as Node: in its corresponding schema.
When this is checked depends on the child's namespace: for children of the schema's own
namespace, at schema load; for children of another namespace, at document
validation (when the node appears).
This rule excludes children without a definition and guarantees that all nodes have defined semantics.
This implies:
- A
Childwithout an explicit namespace MUST have itsNode:definition in the schema itself; its absence MUST cause a schema error at load (section 13). - Declaring
Child: Metadata (org.example.meta)does not require having the schema oforg.example.meta: loading a schema never looks inside other schemas (load-order independence). - If a
Metadata (org.example.meta)node appears in a document, the schema oforg.example.metaMUST be available and MUST defineNode: Metadata; otherwise, it is a document validation error (section 13). A cross-namespace child that is declared but never used poses no problem.
9. Types
Types define:
- The form of the node value (inline,
>>block, both, or none). - Whether the node allows children.
- Content validation.
They are defined inside Node, through a Type element. Example:
9.1 Model of two independent properties
Each type is described through two independent properties:
- Value form:
INLINE,BLOCK,INLINE/BLOCKorNONE. - Allows children: YES or NO.
These two properties are independent from each other. In particular, "allows children" is not derived from the value form. The compatibility rule is as follows:
Only the two generic structural types — INLINE and GROUP — allow children. All
types with specific content validation are leaves (they do not allow children).
Rationale: as soon as a type declares that it validates a specific datum (NUMBER, DATE,
BOOLEAN, ENUM, etc.), that node is a datum, and a datum is a leaf. If both
value and structure are needed, the generic INLINE type is used, which exists precisely for that;
and if only structure is needed, GROUP is used.
Other considerations:
- The type does not control requiredness; only the form and validity of the value. Requiredness of appearance is controlled through cardinality.
- The value of
TypeMUST match exactly one of the types defined in this section. - Declaring
Childrenin aNodewhose type does not allow children MUST cause a schema error.
9.2 Basic structural types
A conforming implementation MUST support these types and MUST validate their structure.
| Type | Value form | Allows children | Description / Validation |
|---|---|---|---|
| INLINE | INLINE | YES | Inline : text. Default type. Optional value without specific validation. Allows children. |
| GROUP | NONE | YES | Does not allow textual value. Structured children only. |
| BLOCK | BLOCK | NO | >> text block only. Does not allow children. |
| TEXT | INLINE/BLOCK | NO | Generic text. It may be inline : or >> block. Does not allow children. |
9.3 Basic INLINE content types
A conforming implementation MUST support these types and MUST validate their structure.
| Type | Value form | Allows children | Description / Validation |
|---|---|---|---|
| BOOLEAN | INLINE | NO | true or false. |
| NUMBER | INLINE | NO | Decimal number, optional sign and exponent (see 9.4). |
| ENUM | INLINE | NO | Only specified values (see 9.6). |
9.4 Extended INLINE content types
A conforming implementation MUST support these types and SHOULD validate their structure.
| Type | Value form | Allows children | Description / Validation |
|---|---|---|---|
| INTEGER | INLINE | NO | Integer with an optional sign. |
| NATURAL | INLINE | NO | Unsigned integer (≥ 0). |
| DATE | INLINE | NO | YYYY-MM-DD date, valid in the calendar. |
| TIME | INLINE | NO | hh:mm:ss time, in range. |
| TIMESTAMP | INLINE | NO | ISO 8601 date and time, YYYY-MM-DDThh:mm[:ss[.f…]][Z|±hh:mm]. |
| UUID | INLINE | NO | 8-4-4-4-12 hexadecimal UUID, case-insensitive. |
| URL | INLINE | NO | Absolute URL: scheme and host required (see below). |
| INLINE | NO | Email address, bare or with a display name (see below). |
Grammar of the types of 9.3 and 9.4. Each type accepts exactly the strings of its rule, applied to the inline value as the parser delivers it (already trimmed). This is the normative grammar: two conforming implementations accept and reject the same values.
BOOLEAN = "true" | "false" ; exact, case-sensitive
NUMBER = [ sign ] ( digits [ "." [ digits ] ] | "." digits ) [ ( "e" | "E" ) [ sign ] digits ]
INTEGER = [ sign ] digits
NATURAL = digits ; no sign
DATE = YYYY "-" MM "-" DD ; an existing date of the (proleptic)
; Gregorian calendar, year 0000–9999
TIME = hh ":" mm ":" ss ; 00–23, 00–59, 00–59; no fraction, no zone
TIMESTAMP = DATE "T" hh ":" mm [ ":" ss [ "." digits ] ] [ "Z" | sign hh ":" mm ]
; same ranges; seconds, fraction and zone optional
UUID = 8hex "-" 4hex "-" 4hex "-" 4hex "-" 12hex ; hex = [0-9A-Fa-f]; version and variant not checked
sign = "+" | "-"
digits = digit { digit } ; ASCII 0–9 only; leading zeros allowed
Details:
NUMBERis not the JSON number: it accepts+1,1.,.5and007. It is a textual value: it is not checked to fit any numeric type of the platform, nor rounded.DATEandTIMESTAMPrequire an existing date:2026-02-30and2026-13-01are invalid,2024-02-29is valid.TIMEandTIMESTAMPrequire a time in range:24:00:00and10:60:00are invalid. Leap seconds (ss= 60) are not accepted.TIMESTAMP: the fraction has one or more digits; without a zone, the interpretation (local time or other) belongs to the application; the zone is validated only syntactically (±hh:mmin range), not checked to exist.- The expressions of this section and those of 9.5 are what a port must implement; nothing is delegated to the platform's date or URL parsers, which disagree with each other.
The EMAIL type accepts two forms, and the address is validated the same way in both:
- The bare address:
[email protected]. - The address preceded by a display name, with the address between
<and>:Joan Costa <[email protected]>. The name is any non-empty text that contains neither<nor>(quotes, if present, are part of the name; they are not interpreted), and the blank between the name and<is optional.
A conforming implementation MUST accept both forms and MUST NOT accept < and >
without a name before them, unbalanced, or followed by anything. This is the usual form of
email headers (the RFC 5322 mailbox), without the quoting and comments of that grammar.
The normative grammar is this (blank is the one of STXT-SPEC §4:
U+0020 or U+0009):
EMAIL = Address
| Name { Blank } "<" Address ">"
Name = non-empty text without "<" or ">", whose last character is not a blank
Address = Local "@" Domain ; at most 254 characters in total
Local = 1*64( atext | "." ) ; 1 to 64 characters
atext = ASCII letter or digit, or one of: ! # $ % & ' * + / = ? ^ _ ` { | } ~ -
Domain = 1*( ASCII letter or digit | "." | "-" ) "." TLD
TLD = 2*63( ASCII letter ) ; 2 to 63 letters
Notes on EMAIL:
- ASCII only: internationalized addresses (EAI) and non-ASCII domains not converted to punycode are not accepted. This is deliberate: a single exact grammar, without Unicode tables that every platform versions its own way.
- Permissive within those limits: the full RFC 5322 dot-atom is not validated
(
[email protected]and[email protected]pass), nor are the domain labels checked one by one (a..b.example.compasses). The value of the type is catching the missing@, blanks, a domain without a dot or a forgotten TLD, not replicating RFC 5322. - The length limits are the practical ones of RFC 5321: 64 characters for the local part and 254 for the whole address; the TLD, 2 to 63 letters.
The URL type accepts only absolute URLs with a scheme and a host. The grammar belongs
to this specification, not to the URL parser of each platform, so that every implementation
accepts exactly the same values:
URL = Scheme "://" [ Userinfo "@" ] Host [ ":" Port ] [ "/" Path ] [ "?" Query ] [ "#" Fragment ]
Scheme = letter { letter | digit | "+" | "-" | "." } ; case-insensitive
Userinfo = one or more characters other than blank, "/", "?", "#" and "@"
Host = "[" one or more of ( hex | ":" | "." ) "]" ; IPv6 in brackets
| one or more characters other than blank, "/", "?", "#", "@", ":", "[" and "]"
Port = digit { digit }
Path = characters other than blank, "?" and "#" ; may be empty
Query = characters other than blank and "#" ; may be empty
Fragment = characters other than blank ; may be empty
Rules:
- A conforming implementation MUST accept any scheme of that form (
https,ftp,git+ssh, …): there is no list of allowed schemes. - The host MUST be non-empty; no top-level domain is required (
http://localhostis valid) and nothing is resolved. Non-ASCII characters are accepted as they are, in the host and elsewhere (an IDN is not converted to punycode). - An implementation MUST NOT accept a value without a scheme (
stxt.dev,www.stxt.dev/x), with a scheme but no//and host (mailto:[email protected],urn:isbn:…,tel:…,file:///etc/hosts), with inner blanks, or with a non-numeric port. - The check is syntactic: nothing is normalised,
%xxescapes are not decoded, and the resource is not checked to exist.
Design note (non-normative): there is deliberately no general URI type. A URI under
RFC 3986 is almost any string with a colon (a:b is one), so such a type would validate
little more than TEXT. The value of URL lies in catching the forgotten scheme or the
misspelled host. For identifiers that are not web addresses (urn:isbn:…, tel:…) use
TEXT or an ENUM; for mail, EMAIL.
9.5 Extended INLINE/BLOCK binary content types
A conforming implementation MUST support these types and MAY validate their structure.
| Type | Value form | Allows children | Description / Validation |
|---|---|---|---|
| HEXADECIMAL | INLINE/BLOCK | NO | [0-9A-Fa-f]+. Hexadecimal string. |
| BINARY | INLINE/BLOCK | NO | [01]+. Binary string. |
| BASE64 | INLINE/BLOCK | NO | Standard Base64: alphabet A–Z a–z 0–9 + /, optional trailing = padding, no leftover bits. |
In all three types, and in both forms, the grammar is applied to the value with no
blanks at all: before validating, every space (U+0020) and tab (U+0009) is removed,
wherever it is, and in the BLOCK form line breaks and empty lines too, so that validation
applies to the concatenation of the lines. This allows grouping digits (DE AD BE EF,
1010 1010) and splitting long content across several lines (e.g. Base64 at 76 columns).
No other character is ignored: a separator other than a blank (DE:AD, DE-AD) is an
invalid value.
BASE64 is the standard alphabet of RFC 4648 §4 (not the URL-safe one with - and _).
The trailing = padding MAY be omitted; the content MUST decode with no leftover
bits, that is, re-encode to the same string (padding aside). An empty string is not valid in
any of the three types.
9.6 ENUM type
The ENUM type allows explicitly enumerating the values allowed for a node.
Rules:
- Comparison MUST be done on the inline value as delivered by the parser (already trimmed left and right, STXT-SPEC §10.1).
- Comparison MUST be exact and CASE-SENSITIVE.
- Comparison MUST NOT apply additional canonicalization, removal of diacritics, nor normalizations equivalent to the canonical name of nodes.
- The node MUST define
ValueswithValuenodes, which represent the allowed values. - Each
ValueMUST be unique and non-empty (section 7.2). ENUMdoes not allow children: aNodeof typeENUMMUST NOT declareChildren.
Example:
A conforming implementation MUST check ENUM types against their allowed values and MUST reject any value that does not match exactly one of them.
Interoperability note (non-normative). The exact comparison is by code points. Values
are literal and are not normalized to NFC (unlike node names,
STXT-SPEC §4.3): café in precomposed form (NFC) and café in
decomposed form (NFD) look identical but do not match. Some input flows — historically,
macOS — produce NFD. Whoever defines ENUM values with diacritics should write them in
NFC, which is what the usual editors produce.
9.7 MARKDOWN type
A conforming implementation MUST support this type.
| Type | Value form | Allows children | Description / Validation |
|---|---|---|---|
| MARKDOWN | INLINE/BLOCK | NO | Text interpreted as Markdown. No structural validation. |
Rules:
- For validation purposes,
MARKDOWNis equivalent toTEXT: all text is valid Markdown, so an implementation MUST NOT reject any value because of its content. - Its function is to be an interpretation contract for consumers (renderers, exporters, editors): the text SHOULD be interpreted according to CommonMark. Extensions (e.g. tables) are the application's decision.
- In the
BLOCKform, line breaks and empty lines are preserved (unlike the binary types of section 9.5): they form part of the Markdown text. - Like every type with specific content,
MARKDOWNdoes not allow children (section 9.1).
Design note (non-normative): MARKDOWN is the only embedded format that
STXT Schema defines, because it covers the only domain that STXT delegates by design —
the formatting of prose (bold, links, lists within text) — and because its raw form
remains readable, consistent with the Human-First principle. Types for embedded data
formats (JSON, XML, YAML, TOML, …) are an explicit non-goal
(section 11): STXT is already the structure format, and such a type would bury structure
in opaque blobs. Structure is expressed in STXT.
10. Cardinalities
Cardinalities are expressed through the Min and Max nodes within each Child.
They are optional non-negative integers that indicate the minimum or maximum number of allowed occurrences of that child.
Rules:
- If
Minis omitted, the effective minimum is0. - If
Maxis omitted, the effective maximum is unlimited. MinandMaxMUST NOT exceed4294967295(2³² − 1); a greater value MUST cause a schema error (CARDINALITY_NOT_VALID). The bound is platform-independent and far above any child count reachable under the recommended parser limits (STXT-SPEC §11.2); "no maximum" is said by omittingMax, not with a giant number.MinandMaxMUST NOT appear more than once within the sameChild.- If both exist,
MinMUST NOT be greater thanMax. Max: 0is legal and declares a forbidden child: theChildexists in the model but no occurrence is valid. It serves, for instance, to withdraw in one version of a namespace a child that another allowed. An implementation MUST NOT treat it as an error.- Cardinality applies per instance of the parent node.
- Cardinality counts only direct children with the same canonical name and the same effective namespace.
- Cardinality validation is independent of child order: it counts occurrences, not positions (see section 11).
- A conforming implementation MUST check cardinalities.
11. Order of children
STXT Schema does not validate the order of children. Validation of cardinality and presence is independent of the position of each child within its parent: it only counts how many times each child appears, not in what order.
Two documents with the same children in a different order validate exactly the same. This is a design decision consistent with the Human-First principle: the author of a document should not have to remember the order of the fields.
Order preserved, not validated. Although order is not validated, the order of appearance of children is preserved in the parsed tree (core guarantee, STXT-SPEC). Therefore, an application that needs positional meaning (for example, consecutive sections of a document) obtains it from the tree itself, not from validation. The semantics of order belong to the application.
Sequential order validation is an explicit non-goal of STXT Schema: introducing
ordered content models (in the style of xs:sequence) would complicate
validators (automata, particle ambiguity) without a clear benefit for the target use cases.
Other explicit non-goals of STXT Schema are: patterns or regular expressions over
values, default values, conditional rules between fields ("if A appears, then B"), and
types for embedded data formats (JSON, XML, YAML, TOML, …; see the design
note in section 9.7). Keeping the model small and predictable is a design goal: that
semantics belongs to the application.
12. Normative Examples
12.1 Schema with cross-namespace references
Schema (@stxt.schema): com.example.docs
Node: Document
Type: GROUP
Children:
Child: Metadata (org.example.meta)
Max: 1
Child: Content
Min: 1
Max: 1
Node: Content
Type: BLOCKAnd in org.example.meta:
12.2 Valid document
12.3 Recursive structure
The closed model allows recursion: a Node may be declared as a child of itself
or of an ancestor.
Schema (@stxt.schema): com.example.docs
Node: Section
Type: GROUP
Children:
Child: Title
Min: 1
Max: 1
Child: Section
Node: Title
Type: INLINEHere Section may contain more nested Section nodes at any depth (limited
by the recommended depth limit in STXT-SPEC, security section).
13. Schema Errors
A schema is invalid if:
- The root node does not have the form
Schema (@stxt.schema): <target_namespace>, or the target namespace is empty or not valid according to STXT-SPEC. - It does not define any
Node. - It defines two
Nodewith the same canonical name. - It uses an unknown
Type. - It defines
Childrenin aNodewhose type does not allow children (section 9). - It defines
Valuesin aNodewhose type is notENUM(section 7.2). - Cardinality is invalid (
Min > Max, a value that is not a non-negative integer, a value greater than4294967295, duplicatedMin/Max). - A
Nodeof typeENUMdoes not defineValues, orValuescontains noValue. - A duplicated
Valueappears after inline normalization by trim. - Two equivalent
Childnodes appear (samecanonical name + effective namespace) within the sameChildren. - A child appears in
Childrenof the schema's own namespace whoseNodeis not defined in the schema itself. - The schema document has more than one root node, or none: a schema document is exactly one
Schemanode. - A node of the schema (
Node,Child,Type,Min…) is written in>>form; all of them are inline exceptDescription, which isTEXT. - A
Valueof anENUMis empty (section 7.2).
A document is invalid against a schema if:
- A node presents a direct undeclared child in the
Childrenof its definition (closed model, section 6). - A node without declared
Childrenpresents any direct child. - A declared cardinality is violated.
- The value of a node does not satisfy validation of its type.
- The form of the node (inline or
>>block, value present or absent, with or without children) is not the one of its type (section 9). - An
ENUMvalue does not match exactly any of itsValue. - A node with a non-empty namespace appears that has no schema available (
SCHEMA_NOT_FOUND; nodes with namespace""are not validated, section 5), or whose name does not exist as aNode:in the schema of its namespace (section 8.1).
13.1 Error codes
As in STXT-SPEC §11.1, every error carries a stable code, identical
in every implementation, and is never renamed. A schema document is first
validated as a document against the meta-schema of section 15, so its form errors
(a Node without a value, two Type, a Min that is not a NATURAL…) come with the codes
of the second table; the rules of the first are applied afterwards.
Errors of the schema (first list of this section):
| Code | Condition |
|---|---|
SCHEMA_ROOT_NOT_VALID |
1: the root is not Schema (@stxt.schema): …, or the target namespace is not valid |
SCHEMA_NAMESPACE_EMPTY |
1: the target namespace is empty |
SCHEMA_MULTIPLE_ROOTS |
12: the schema document has more than one root node, or none |
SCHEMA_NODE_NOT_INLINE |
13: a node of the schema is written in >> form |
NODE_DUPLICATED |
3: two Node with the same canonical name |
INVALID_NODE_NAME |
the value of a Node or a Child is not a valid name (section 7.1) |
TYPE_NOT_VALID |
4: unknown type (the meta-schema catches it first as INVALID_VALUE of the Type ENUM; TYPE_NOT_VALID is left for an implementation whose type registry lacks the type) |
CHILDREN_NOT_ALLOWED_FOR_TYPE |
5: Children on a type that allows no children |
VALUES_NOT_ALLOWED_FOR_TYPE |
6: Values on a type other than ENUM |
CARDINALITY_NOT_VALID |
7: Min or Max is not a non-negative integer, or exceeds 4294967295 |
MIN_GREATER_THAN_MAX |
7: Min greater than Max |
VALUES_REQUIRED |
8: ENUM without Values, or Values without any Value |
VALUE_DUPLICATED |
9: two equal Value after trimming |
VALUE_EMPTY |
14: a Value of an ENUM without a value |
VALUES_DUPLICATED |
two Values nodes in the same Node |
CHILD_DUPLICATED |
10: two Child with the same canonical name + namespace pair |
CHILD_NOT_DEFINED |
11: a Child of the same namespace without its Node |
Errors of the document against the schema (second list):
| Code | Condition |
|---|---|
SCHEMA_NOT_FOUND |
node with a non-empty namespace and no schema available |
NODE_NOT_DEFINED_IN_SCHEMA |
the node's name does not exist as a Node in the schema of its namespace |
CHILD_NOT_DECLARED |
direct child not declared in Children (closed model), or any child under a Node without Children |
TOO_FEW_CHILDREN |
fewer occurrences of a child than its Min |
TOO_MANY_CHILDREN |
more occurrences of a child than its Max |
INVALID_VALUE |
the value does not follow the grammar of its type, or is not one of the Value of an ENUM |
BLOCK_FORM_REQUIRED |
inline form where the type requires a >> block (BLOCK) |
BLOCK_FORM_NOT_ALLOWED |
>> block form where the type requires inline |
VALUE_NOT_ALLOWED |
a value on a node of type GROUP |
CHILDREN_NOT_ALLOWED |
children under a node of type TEXT or MARKDOWN |
TYPE_NOT_VALID |
the type declared in the schema does not exist in the implementation |
UNEXPECTED_ERROR |
unforeseen exception of the implementation, with the node's line |
14. Conformance
An implementation is conforming if:
- It fully implements this document.
- It validates types, value forms, cardinalities, and allowed values (ENUM).
- It applies the closed content model (section 6).
- It applies the child compatibility rule by type (only
INLINEandGROUPallow children). - It applies the strict mandatory definition rule for all nodes referenced in
Children(at schema load for children of the same namespace; at document validation for cross-namespace children, section 8.1). - It validates cardinalities independently of order.
- It selects, for each validation, a single effective schema per namespace, and does not validate nodes with an empty namespace (section 5).
- It rejects invalid documents and schemas.
15. Schema of the Schema (@stxt.schema)
This section defines the official schema of the schema system itself: the meta-schema that validates all documents in the @stxt.schema namespace.
Level of guarantee. The meta-schema validates the form of a schema document (which nodes
exist, their types, their cardinalities). It cannot express the conditional or
crossed rules of this document (for example "Values only if Type: ENUM", or "Min ≤ Max"),
which belong to the language but not to the meta-schema. Therefore, "validating against the meta-schema"
is a necessary but not sufficient condition to be a valid schema: in addition, the rules of section 13 must be met.
15.1 Considerations
- Every schema document is:
Schema (@stxt.schema): <target-namespace> - A schema contains:
- Optionally a
Description. - One or more
Nodenodes.
- Optionally a
- Each
Node:- Has an inline value (the node name of the target namespace).
- May optionally have:
DescriptionTypeChildrenValues
- Each
Child(Childrenelement) defines the name (and optionally a different namespace) and may have:Min: Minimum number of nodes that must appear. If the node does not exist there is no established minimum.Max: Maximum number of nodes that may appear. If the node does not exist there is no established maximum.
- Each
Values:- May only appear in
Nodenodes of typeENUM. - Contains one or more
Valuenodes.
- May only appear in
- The names (
Schema,Node,Type,Children,Child,Description,Min,Max,Values,Value) belong to the@stxt.schemanamespace.
15.2 Complete Meta-Schema
Schema (@stxt.schema): @stxt.schema
Node: Schema
Children:
Child: Description
Max: 1
Child: Node
Min: 1
Node: Node
Children:
Child: Type
Max: 1
Child: Children
Max: 1
Child: Description
Max: 1
Child: Values
Max: 1
Node: Children
Type: GROUP
Children:
Child: Child
Min: 1
Node: Description
Type: TEXT
Node: Child
Children:
Child: Min
Max: 1
Child: Max
Max: 1
Node: Min
Type: NATURAL
Node: Max
Type: NATURAL
Node: Type
Type: ENUM
Values:
Value: INLINE
Value: BLOCK
Value: TEXT
Value: GROUP
Value: BOOLEAN
Value: NUMBER
Value: ENUM
Value: INTEGER
Value: NATURAL
Value: DATE
Value: TIME
Value: TIMESTAMP
Value: UUID
Value: URL
Value: EMAIL
Value: HEXADECIMAL
Value: BINARY
Value: BASE64
Value: MARKDOWN
Node: Values
Type: GROUP
Children:
Child: Value
Min: 1
Node: ValueNote: in the meta-schema, Node and Child are of default type INLINE (their
inline value is the name of the target node or child) and therefore they allow children. This illustrates that
INLINE is the type that combines value and structure, the core of the system.
15.3 Quick reading
-
SchemaInline value = target namespace (e.g.com.example.docs). Children:Description(?),Node(+). -
NodeInline value = target node name (e.g.Document,Author). Optional children:Type: concrete type (if missing ⇒INLINE).Children: Node with list of allowedChild.Description: explanatory text.Values: Allowed values (ENUM type only).
-
TypeInline (ENUM), with the type name (GROUP,INLINE,NUMBER, etc.). -
ChildrenGROUP: contains one or moreChildnodes. -
DescriptionTEXT: may be inline or multiline. -
ValuesGROUP: contains one or moreValuenodes. -
ValueInline value with one of the allowed values for theENUM.