STXT Templates (@stxt.template)
1. Introduction2. Terminology
3. Relationship between STXT and Template
4. General Structure of a Template
5. One template per target namespace
6. `Structure >>` Block
7. Cardinalities
8. Types
9. ENUM and value list
10. Namespaces within `Structure`
11. Rules for "defined nodes"
12. Compilation to Schema (semantic equivalence)
13. Template Errors
14. Conformance
15. Meta-template of the `@stxt.template` system itself
16. Normative examples
17. Appendix A — Grammar (informal)
18. End of Document
1. Introduction
This document defines the specification of the STXT Template language, a mechanism for describing semantic rules (structure, types, cardinalities, and allowed values) applicable to STXT documents.
A template:
- Is an STXT document whose namespace is
@stxt.template. - Is associated with a target namespace, analogously to a schema.
- Describes the expected structure through a
Structure >>block with simplified syntax. - Can be compiled into a semantically equivalent
@stxt.schemadocument within the subset expressible by templates.
Relationship with @stxt.schema:
- An implementation MAY support only schemas, only templates, or both.
- If both exist (schema and template) for the same target namespace, a conforming implementation SHOULD establish a consistent prioritization criterion.
- For a specific validation, an implementation MUST use a single effective semantic source: either schema or template.
- STXT core MUST NOT impose semantics: templates are an optional layer, after parsing the STXT document.
2. Terminology
The keywords "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" must be interpreted according to RFC 2119.
Terms such as node, indentation, namespace, inline, and >> block retain their meaning in STXT-SPEC.
Additional definitions:
- Target namespace: the STXT namespace to which the template applies (for example
com.example.docs). - Node template: an entry within the
Structure >>block that defines a node (and optionally its type/cardinality and its children). - Type: a semantic validation label (for example
TEXT,DATE,ENUM) equivalent to the types in STXT Schema. - Cardinality: a rule that defines how many times a child node may appear relative to its parent.
3. Relationship between STXT and Template
Validation through templates occurs after STXT parsing:
- Parsing the STXT document into a hierarchical structure.
- Resolving the effective namespace of each node.
- Selecting the corresponding template for the target namespace.
- Applying template rules (structure, cardinality, types, values).
An implementation MAY apply rules during parsing, provided that this validation remains loosely coupled to the base parser.
4. General Structure of a Template
A template document MUST have as its root node:
Template (@stxt.template): <target_namespace>
The template MUST contain exactly one Structure node in block form (>>).
Template (@stxt.template): com.example.docs
Description: Example template
Structure >>
Document (com.example.docs):
Title: (1)
Body: (1) TEXT
Rules:
- The root node
TemplateMUST belong to the namespace@stxt.template. <target_namespace>MUST be a valid namespace according to STXT-SPEC (namespaces section).- The template document MAY include a
Descriptionnode. - There can only be one effective template per target namespace in a specific validation (see section 5).
5. One template per target namespace
For each logical namespace:
- There MUST NOT be more than one effective template simultaneously.
- If there are multiple candidate templates for the same namespace, the implementation SHOULD have a clear, stable, and deterministic criterion for deciding which one applies.
- For a specific validation, an implementation MUST NOT apply multiple templates at once to the same target namespace.
6. `Structure >>` Block
The Structure >> block defines a tree of node templates using indentation, where:
- Each non-empty line defines a node template.
- Indentation defines child nodes (just like STXT), but inside
Structure >>a data document is not being described, but rather an expected structure. - The indentation rules of the base STXT document apply to the template document outside the block.
- The content of
Structure >>is interpreted through the template grammar defined in this document. - The hierarchy within
Structure >>MUST be built with the same consecutive indentation model as in STXT-SPEC.
Top level and defined nodes. The top-level lines of Structure do not have
special "root" semantics: they are node templates like any other, and their nesting defines
their children. Each line of Structure (at any level) defines or references a node of the
corresponding namespace, exactly like a Node in a schema.
6.1 Recommended style convention
For readability, it is recommended:
- 1 tab per level.
- A single space between components.
- Maintain consistency in names (use the same capitalization/diacritics as in real documents).
6.2 Syntax of a `Structure` line
Each line of the Structure >> block has the form:
<NodeName> [<NamespaceOverride>] ":" [<RuleSpec>]
where:
<NodeName>is the node name (human text; normalized according to STXT-SPEC for comparison).<NamespaceOverride>is optional and has the form(<namespace>)or(@special.namespace)and defines the effective namespace of that template node.":"is mandatory (to be a valid STXT document).<RuleSpec>is optional and includes, in this logical order:- Optional cardinality (in parentheses).
- Optional reference to a node through
@Node Name, or alternatively a type. - Optional values if the type is
ENUM.
Examples:
Title:
Title: (1)
Body: (1) TEXT
Color: (?) ENUM [red, green, blue]
Body Content: (?) @Body Content
Metadata (org.example.meta): (0,1)
Notes:
- If
<RuleSpec>is omitted entirely, default cardinality and default type are assumed (sections 7 and 8). - A template node may have children if its effective type allows them. The default type
INLINEallows children. Types that forbid children are defined in section 8. - A reference
@Node NameMUST NOT be combined with an explicit type on the same line.
6.3 Parsing rules for `Structure >>`
A template parser MUST:
-
Read the
Structure >>block as a sequence of lines (already canonicalized by STXT core: right trim per line). -
Ignore empty lines.
-
Compute hierarchy by indentation (same principles as STXT: consecutive indentation, without jumps).
-
For each line, parse:
- Node name + optional namespace
(ns)if present. - The mandatory
:character. - The optional rule specification (
RuleSpec).
- Node name + optional namespace
-
Resolve the effective namespace of each line.
-
Resolve
@Node Namereferences according to section 6.4.
A template parser MUST fail if a line does not contain :.
6.4 Definition, reference, and recursion
Templates distinguish between:
- Local node definition: appearance of a node whose effective namespace belongs to the template's target namespace, with its complete
RuleSpec(type, values, children). - Local node reference: reuse of a local definition through
@Node Name. - External reference: appearance of a node whose effective namespace belongs to another namespace.
Rules for definition and reference:
- A local node MUST NOT be defined more than once per pair
canonical name + effective namespace. - If a local node appears again elsewhere in
Structure, it MUST be done through a@Node Namereference. - A
@Node Namereference MAY override cardinality, but MUST NOT redefine type,ENUMvalues, or children. - The canonical name of the line and the canonical name of the
@Node Namereference MUST match. A reference with a different name from its line MUST cause a template error (there is no renaming:@marks "reappearance of the same node", not "pointer to another"). - Nodes from other namespaces MUST NOT be defined locally within the current template.
- An external node MAY appear multiple times, but that line SHOULD declare only its cardinality.
Recursion. A @Node Name reference MUST point to:
- a previous local definition (already closed) in the same template, or
- an ancestor node whose definition is open at that point, including the very node being defined.
This second option enables recursive structures: a node may be declared as a child of itself or of an ancestor. To resolve the reference only the node's identity is needed (name + namespace + type), which is already available on its definition line; it is not necessary for its list of children to be complete.
Since writing Structure is equivalent to a depth-first traversal of the node graph, this rule
covers any dependency graph: self-recursion, recursion through ancestors, and mutual
recursion.
Example (self-recursion):
Template (@stxt.template): com.example.doc
Structure >>
Document (com.example.doc):
Title: (1)
Section: (*)
Title: (1) @Title
Text: (?) TEXT
Section: (*) @Section
Here the last line, Section: (*) @Section, declares Section as a child of itself,
referencing the ancestor Section whose definition is open. Title: (1) @Title
reuses the previous local definition of Title.
Example (mutual recursion A/B):
Template (@stxt.template): com.example.tree
Structure >>
A (com.example.tree):
B: (*)
A: (?) @A
7. Cardinalities
Cardinality applies per instance of the parent node, counting only direct children that match by:
- Canonical node name (according to STXT-SPEC).
- Effective namespace of the node.
Cardinality is expressed as an optional token in parentheses: ( ... ).
It is independent of the order of the children (it counts occurrences, not positions).
7.1 Allowed forms
Allowed forms:
| Form | Meaning |
|---|---|
num |
Exactly num. |
* |
Any number (0..∞). |
+ |
One or more (1..∞). |
? |
Zero or one (0..1). |
num+ |
num or more (num..∞). |
num- |
Up to num (0..num). |
min,max |
Between min and max. |
Rules:
num,min, andmaxMUST be non-negative integers.- In
min,max,min <= maxMUST hold. +is equivalent to1+.?is equivalent to0,1.- The default cardinality, if omitted, is
*.
7.2 Default cardinality
If cardinality is not specified, the default value is:
*(any number).
8. Types
Types in templates reuse the set of types from STXT Schema, with the same intent: validate the form of the value and, optionally, its content.
The type is specified as a word after the cardinality (if present).
Examples:
Date: (1) DATE
Body: (1) TEXT
Is Public: (1) BOOLEAN
General rules:
- The explicit type MUST match exactly one of the types supported by the implementation.
- If a line uses a
@Node Namereference, it MUST NOT also declare an explicit type. - The semantic rules of types
INLINE,GROUP,BLOCK,TEXT,ENUM,NUMBER,DATE, etc. MUST be consistent with those defined in STXT-SCHEMA-SPEC.
8.1 Default type
If the type is omitted, the default type is:
INLINE
8.2 Compatibility with children
The compatibility rule with children is the same as in STXT-SCHEMA-SPEC (section 9):
Only types INLINE and GROUP allow children. All others are leaves.
Therefore:
- If a template node declares children in
Structure >>, its effective type MUST beINLINEorGROUP. Otherwise, the template MUST be considered invalid. - The default type
INLINEallows children, so a node without an explicit type may have children. - Any type with content validation (
BLOCK,TEXT,NUMBER,BOOLEAN,DATE,ENUM,BASE64, etc.) DOES NOT allow children.
8.3 Type set
The recommended type set is the same as STXT-SCHEMA-SPEC.
A template implementation:
- MUST support at least:
INLINE,GROUP,BLOCK,TEXT,NUMBER,BOOLEAN,DATE,ENUM. - SHOULD support the rest of the types defined in STXT Schema (for example
INTEGER,NATURAL,TIME,TIMESTAMP,UUID,URL,EMAIL,BASE64, etc.).
9. ENUM and value list
If the type is ENUM, the template MUST declare a list of allowed values, with at least one value.
The value list is specified with brackets [...] after the type:
ENUM [value1, value2, value3]
Color: (1) ENUM [red, green, blue]
Rules:
- If the type is
ENUM, the value list MUST exist for it to have valid content. - If the type is NOT
ENUM, a[...]list MUST be considered a template error. - Values are separated by commas
,. - Trim is applied (spaces/tabs) around each value.
- Value comparison MUST be done on the inline value already normalized through left/right trim.
- Value comparison MUST be exact and CASE-SENSITIVE.
- Comparison MUST NOT apply additional canonicalization, removal of diacritics, or normalization equivalent to the canonical name of nodes.
- At least one value must exist in the list.
- Values MUST NOT be repeated after applying normalization trim.
9.1 Limitation of list syntax
Because of the form of the syntax [a, b, c], an ENUM value declared in a template CANNOT
contain a comma , (value separator) or a closing bracket ] (end of list).
It also does not preserve spaces at the beginning or end, which trim removes.
This is a limitation of the subset expressible by templates. If ENUM values
with commas, brackets, or significant spaces are needed, a schema (@stxt.schema) must be used,
whose Value nodes allow any inline value.
10. Namespaces within `Structure`
Each line may include an explicit namespace for the template node:
Metadata (org.example.meta): (?)
Rules:
- If a
Structureline omits an explicit namespace, it inherits the effective namespace of its parent. - If the node has no parent within
Structure, the default namespace is the template's target namespace. - Namespace inheritance works as in STXT data documents.
- If
(other.ns)is specified, that template node belongs to that other namespace. - If
(other.ns)is specified and that namespace is different from the target namespace, the line MUST NOT define children, explicit type, orENUMvalues; it MAY only declare cardinality.
11. Rules for "defined nodes"
In templates, a node becomes defined by its appearance in Structure.
Unlike Schema, there is no separate Node: section; the structure itself is the definition.
Rules:
- Every local node defined in
Structurebecomes part of the template's set of nodes. - If a template references cross-namespace nodes, a complete validation system SHOULD have the corresponding template or schema for that external namespace if it wishes to deeply validate those nodes.
- An implementation MAY validate only cardinality and structure of the target namespace, treating cross-namespace nodes as a "black box", depending on configuration.
12. Compilation to Schema (semantic equivalence)
A template can be compiled into an equivalent schema:
- Each local node defined in
Structuregenerates aNodedefinition (in the corresponding namespace). - The indentation hierarchy in
StructuregeneratesChildren/Childin the schema. - Cardinality
( ... )in the template is translated toMin/Maxin the schema. - The type is copied to
Type. ENUM [a,b]is translated toValues/Value.- A
@Node Namereference reuses the definition already generated for that local node and only modifies the cardinality of the correspondingChild. Recursion (self-reference or open ancestor) is translated to aChildthat points to the sameNode. - A cross-namespace node only generates a
Childreference; its definition corresponds to the template or schema of that other namespace.
Rules for cardinality translation:
(num)→Min=num,Max=num(*)→ withoutMin, withoutMax(+)→Min=1(?)→Max=1(num+)→Min=num(num-)→Max=num(min,max)→Min=min,Max=max
13. Template Errors
A template is invalid if any of these conditions occurs:
- The
Structure>>document is not a valid STXT document (invalid indentation, etc.) - The document does not have root
Template (@stxt.template): <target_namespace>. Structure >>is missing orStructureis not a>>block.- A non-empty line within
Structuredoes not contain:. - Malformed cardinality or cardinality with invalid numbers.
- Unknown type (according to the set of types supported by the implementation).
- Use of
[...]if the type is notENUM. - A node with children has an effective type that does not allow children (that is, different from
INLINEorGROUP). - Redefining a local node that has already appeared previously without using
@Node Namereference. - Using a
@Node Namereference that does not point to a previous local definition or to an open ancestor. - The name of a
@Node Namereference does not match (in canonical name) the name of its line. - Declaring both
@Node Namereference and explicit type on the same line. - Declaring duplicate
ENUMvalues after trim normalization. - Defining children, explicit type, or
ENUMvalues on a cross-namespace node.
14. Conformance
A template implementation is conformant if:
- It implements the
TemplateandStructuregrammar of this document. - It applies the rules of cardinality, types,
@Node Namereferences (including recursion through open ancestor), andENUM. - It applies the child compatibility rules by type (only
INLINEandGROUPallow children). - It validates cardinalities independently of order.
- It rejects invalid templates according to section 13.
- It defines a stable template selection criterion (if multiple sources exist), without applying more than one simultaneously per target namespace.
15. Meta-template of the `@stxt.template` system itself
This section defines a recommended minimal template for validating documents in the @stxt.template namespace.
Template (@stxt.template): @stxt.template
Structure >>
Template (@stxt.template):
Description: (?) TEXT
Structure: (1) BLOCK
Notes:
StructureisBLOCKbecause in templates it must be a>>block.Descriptionis optional and may beTEXT.- The
Templateline uses default cardinality (*): since the top level ofStructurehas no special root semantics (section 6), no document cardinality is imposed on it.
16. Normative examples
16.1 Simple template (one namespace)
Template (@stxt.template): com.example.docs
Description: Simple template
Structure >>
Document (com.example.docs):
Title: (1)
Author: (1)
Date: (1) DATE
Body: (1) TEXT
16.2 Template with repetition and nested nodes
Template (@stxt.template): com.example.blog.post
Structure >>
Post (com.example.blog.post):
Title: (1)
Slug: (1)
Published: (1) BOOLEAN
Tags: (?)
Tag: (+)
Sections: (1)
Section: (+)
Heading: (1)
Content: (1) TEXT
16.3 Template with ENUM
Template (@stxt.template): com.example.ui.theme
Structure >>
Theme (com.example.ui.theme):
Name: (1)
Mode: (1) ENUM [light, dark]
Accent: (?) ENUM [blue, green, orange]
16.4 Template with local reuse
Template (@stxt.template): org.example.docs
Structure >>
Email (org.example.docs):
Body Content: (1) TEXT
Demo (org.example.docs):
Body Content: (?) @Body Content
16.5 Template with recursion
Template (@stxt.template): com.example.doc
Structure >>
Document (com.example.doc):
Title: (1)
Section: (*)
Title: (1) @Title
Text: (?) TEXT
Section: (*) @Section
Section contains itself at any depth. This is the case that a parser with the
"previous definition only" rule would incorrectly reject; that is why it is included as a
normative example of conformance.
16.6 Cross-namespace (external references)
Template (@stxt.template): com.example.docs
Structure >>
Document (com.example.docs):
Metadata (org.example.meta): (?)
Content: (1) TEXT
In this case:
Metadatabelongs toorg.example.meta.- Deep validation of
Metadatawill depend on whether a schema/template exists fororg.example.meta.
17. Appendix A — Grammar (informal)
TemplateDoc = "Template" "(" "@stxt.template" ")" ":" NamespaceTarget { TemplateField }
TemplateField = DescriptionField | StructureField
DescriptionField = "Description" ":" Text
StructureField = "Structure" ">>" Newline { StructureLine }
StructureLine = Indent NodeSpec Newline
NodeSpec = NodeName [NsOverride] ":" [RuleSpec]
NsOverride = "(" ["@"] Namespace ")"
RuleSpec = [Card] [NodeRef | Type [EnumValues]]
Card = "(" CardToken ")"
CardToken = "*" | "+" | "?" | Num | Num "+" | Num "-" | Num "," Num
NodeRef = "@" NodeName
Type = IdentUpper
EnumValues = "[" Value { "," Value } "]"
NodeName = Text up to `(` or `:`, with trim and space compaction
NamespaceTarget = Namespace according to STXT-SPEC
Namespace = Ident "." Ident { "." Ident } ; at least 2 Ident
Ident = [A-Za-z0-9]+ ; accepted in input; normalized to lowercase (STXT-SPEC section 7)
IdentUpper = [A-Z0-9_]+ ; recommended in uppercase (style)
Value = any text without "," or "]", with trim ; see section 9.1