STXT - Semantic Text
Built for humans. Reliable for machines.

STXT Templates (@stxt.template)

1. Introduction
2. 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:

Relationship with @stxt.schema:

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:

3. Relationship between STXT and Template

Validation through templates occurs after STXT parsing:

  1. Parsing the STXT document into a hierarchical structure.
  2. Resolving the effective namespace of each node.
  3. Selecting the corresponding template for the target namespace.
  4. 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:

5. One template per target namespace

For each logical namespace:

6. `Structure >>` Block

The Structure >> block defines a tree of node templates using indentation, where:

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:

6.2 Syntax of a `Structure` line

Each line of the Structure >> block has the form:

<NodeName> [<NamespaceOverride>] ":" [<RuleSpec>]

where:

Examples:

Title:
Title: (1)
Body: (1) TEXT
Color: (?) ENUM [red, green, blue]
Body Content: (?) @Body Content
Metadata (org.example.meta): (0,1)

Notes:

6.3 Parsing rules for `Structure >>`

A template parser MUST:

  1. Read the Structure >> block as a sequence of lines (already canonicalized by STXT core: right trim per line).

  2. Ignore empty lines.

  3. Compute hierarchy by indentation (same principles as STXT: consecutive indentation, without jumps).

  4. For each line, parse:

    • Node name + optional namespace (ns) if present.
    • The mandatory : character.
    • The optional rule specification (RuleSpec).
  5. Resolve the effective namespace of each line.

  6. Resolve @Node Name references 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:

Rules for definition and reference:

Recursion. A @Node Name reference MUST point to:

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:

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:

7.2 Default cardinality

If cardinality is not specified, the default value is:

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:

8.1 Default type

If the type is omitted, the default type is:

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:

8.3 Type set

The recommended type set is the same as STXT-SCHEMA-SPEC.

A template implementation:

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:

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:

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:

12. Compilation to Schema (semantic equivalence)

A template can be compiled into an equivalent schema:

Rules for cardinality translation:

13. Template Errors

A template is invalid if any of these conditions occurs:

  1. The Structure>> document is not a valid STXT document (invalid indentation, etc.)
  2. The document does not have root Template (@stxt.template): <target_namespace>.
  3. Structure >> is missing or Structure is not a >> block.
  4. A non-empty line within Structure does not contain :.
  5. Malformed cardinality or cardinality with invalid numbers.
  6. Unknown type (according to the set of types supported by the implementation).
  7. Use of [...] if the type is not ENUM.
  8. A node with children has an effective type that does not allow children (that is, different from INLINE or GROUP).
  9. Redefining a local node that has already appeared previously without using @Node Name reference.
  10. Using a @Node Name reference that does not point to a previous local definition or to an open ancestor.
  11. The name of a @Node Name reference does not match (in canonical name) the name of its line.
  12. Declaring both @Node Name reference and explicit type on the same line.
  13. Declaring duplicate ENUM values after trim normalization.
  14. Defining children, explicit type, or ENUM values on a cross-namespace node.

14. Conformance

A template implementation is conformant if:

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:

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:

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

18. End of Document