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

STXT Esquemas (@stxt.schema)

1. Introducción
2. Terminología
3. Relación entre STXT y Schema
4. Estructura general de un Esquema
5. Un schema por namespace
6. Modelo de contenido cerrado
7. Definición de Nodos (`Node:`)
8. Hijos (`Children:`) y namespaces cruzados
9. Tipos
10. Cardinalidades
11. Orden de los hijos
12. Ejemplos Normativos
13. Errores de Schema
14. Conformidad
15. Schema del Schema (`@stxt.schema`)
16. Fin del Documento

1. Introducción

Este documento define la especificación del lenguaje STXT Schema, un mecanismo para validar documentos STXT mediante reglas semánticas formales.

Un schema:

2. Terminología

Las palabras clave "DEBE", "NO DEBE", "DEBERÍA", "NO DEBERÍA", y "PUEDE" deben interpretarse según RFC 2119.

Términos como nodo, indentación, namespace, inline y bloque >> mantienen su significado en STXT-SPEC.

3. Relación entre STXT y Schema

La validación mediante schema ocurre después del parseo STXT:

  1. Parseo del documento a una estructura jerárquica STXT.
  2. Resolución del namespace efectivo de cada nodo.
  3. Aplicación del schema correspondiente.

Una implementación PUEDE aplicar la validación durante el proceso de parseo, siempre que dicha validación permanezca débilmente acoplada al parser base. Esto permite detectar errores antes de finalizar el parseo completo.

4. Estructura general de un Esquema

Un documento schema DEBE tener como nodo raíz:

Schema (@stxt.schema): <namespace_objetivo>

Reglas:

Ejemplo:

Schema (@stxt.schema): com.example.docs
    Description: Schema de ejemplo
    Node: Document
        Type: GROUP
        Children:
        	Child: Autor
        	Child: Fecha
        		Max: 1
        	Child: Content
        		Min: 1
        		Max: 1
        	Child: Metadata (org.example.meta)
        		Max: 1
    Node: Autor
    Node: Fecha
        Type: DATE
    Node: Content
        Type: TEXT

5. Un schema por namespace

Para cada namespace lógico:

6. Modelo de contenido cerrado

STXT Schema usa un modelo de contenido cerrado. Esto significa que, para cada nodo del documento, sólo se permiten los hijos directos declarados explícitamente en el schema.

Reglas:

Este modelo es coherente con la filosofía de STXT de fallar de forma ruidosa: un nodo mal escrito (por ejemplo Titel en lugar de Title) se detecta como hijo no declarado en lugar de aceptarse silenciosamente.

Nota sobre evolución. Como el modelo es cerrado, añadir un nodo a un namespace es un cambio que rompe la validación de documentos que usen schemas antiguos. La práctica recomendada para evolucionar un namespace de forma incompatible es versionarlo en el propio namespace (por ejemplo com.example.docs.v1com.example.docs.v2), de modo que cada versión tenga su schema y los documentos declaren la versión que usan.

Nodos cross-namespace no resueltos. Si un Child apunta a otro namespace y la implementación no dispone de schema para ese namespace, el nodo declarado se acepta, pero su contenido interno queda sin validar ("caja negra"). Una implementación DEBERÍA poder distinguir entre "validado completamente" y "validado parcialmente" en ese caso (ver sección 7.1).

7. Definición de Nodos (`Node:`)

7.1 Forma básica

Node: Nombre Nodo
	Description: Descripción del nodo
    Type: Tipo
    Children:
    	Child: Nombre Hijo. Puede incluir un namespace si es distinto del namespace objetivo
    		Min: opcional, indica el número mínimo de hijos que pueden aparecer
    		Max: opcional, indica el número máximo de hijos que pueden aparecer

Reglas:

7.2 Valores en tipos ENUM

Node: Nombre Nodo
	Description: Descripción del nodo
    Type: ENUM
    Values:
    	Value: valor 1
    	Value: valor 2
    	Value: valor 3

El tipo ENUM, y sólo ENUM, PUEDE especificar un nodo Values con los valores permitidos mediante nodos Value. Si existe Values, DEBE contener al menos un nodo Value. Si un Node declara Type: ENUM, DEBE incluir Values.

Como ENUM no admite hijos (sección 9), un Node de tipo ENUM NO DEBE declarar Children.

8. Hijos (`Children:`) y namespaces cruzados

Un nodo PUEDE tener una entrada Children. Si existe Children, DEBE contener uno o más nodos Child con la información de los hijos permitidos.

Un Child PUEDE pertenecer a otro namespace, en cuyo caso se indica en el nombre del propio Child. Ejemplo:

Node: nombre del nodo
	Children:
		Child: nombre del hijo (namespace.del.hijo)
			Min: 0
			Max: 1

8.1 Nodos definidos explícitamente

Todo nodo que aparezca en Children debe tener una definición propia como Node: en su schema correspondiente.

Así evitamos hijos "fantasma" y garantizamos que todos los nodos tienen semántica definida.

Esto implica:

9. Tipos

Los tipos definen:

  1. La forma del valor del nodo (inline, bloque >>, ambas o ninguna).
  2. Si el nodo admite hijos.
  3. La validación del contenido.

Se definen dentro de Node, mediante un elemento Type. Ejemplo:

Node: nombre del nodo
	Type: TIPO_DEL_NODO
	Children:
		Child: Nombre Hijo

9.1 Modelo de dos propiedades independientes

Cada tipo se describe mediante dos propiedades independientes:

Estas dos propiedades son independientes entre sí. En particular, "admite hijos" no se deriva de la forma del valor. La regla de compatibilidad es deliberadamente simple:

Sólo los dos tipos estructurales genéricos — INLINE y GROUP — admiten hijos. Todos los tipos con validación de contenido específico son hojas (no admiten hijos).

La intuición: en cuanto un tipo declara que valida un dato concreto (NUMBER, DATE, BOOLEAN, ENUM, etc.), ese nodo es un dato, y un dato es una hoja. Si se necesita valor más estructura, se usa el tipo genérico INLINE, que existe precisamente para eso; y si se necesita sólo estructura, se usa GROUP.

Otras consideraciones:

9.2 Tipos estructurales básicos

Una implementación conforme DEBE admitir estos tipos y DEBE validar su estructura.

Tipo Forma del valor Admite hijos Descripción / Validación
INLINE INLINE Texto inline :. Tipo por defecto. Valor opcional sin validación específica. Admite hijos.
GROUP NONE No admite valor textual. Sólo hijos estructurados.
BLOCK BLOCK NO Sólo bloque >> de texto. No admite hijos.
TEXT INLINE/BLOCK NO Texto genérico. Puede ser inline : o bloque >>. No admite hijos.

9.3 Tipos básicos de contenido INLINE

Una implementación conforme DEBE admitir estos tipos y DEBE validar su estructura.

Tipo Forma del valor Admite hijos Descripción / Validación
BOOLEAN INLINE NO true o false.
NUMBER INLINE NO Número con formato JSON.
ENUM INLINE NO Sólo valores especificados (ver 9.6).

9.4 Tipos ampliados de contenido INLINE

Una implementación conforme DEBE admitir estos tipos y DEBERÍA validar su estructura.

Tipo Forma del valor Admite hijos Descripción / Validación
INTEGER INLINE NO Número sin decimales (positivos y negativos).
NATURAL INLINE NO Números mayores o iguales a 0 sin decimales.
DATE INLINE NO Fecha YYYY-MM-DD.
TIME INLINE NO Hora ISO 8601, hh:mm:ss.
TIMESTAMP INLINE NO Timestamp ISO 8601 completo.
UUID INLINE NO UUID canónico.
URL INLINE NO URL o URI válida.
EMAIL INLINE NO Dirección de correo válida.

9.5 Tipos ampliados de contenido binario INLINE/BLOCK

Una implementación conforme DEBE admitir estos tipos y PUEDE validar su estructura.

Tipo Forma del valor Admite hijos Descripción / Validación
HEXADECIMAL INLINE/BLOCK NO [0-9A-Fa-f]+. Cadena hexadecimal.
BINARY INLINE/BLOCK NO [01]+. Cadena binaria.
BASE64 INLINE/BLOCK NO Contenido Base64 válido.

9.6 Tipo ENUM

El tipo ENUM permite enumerar de forma explícita los valores permitidos para un nodo. Reglas:

Ejemplo:

Node: Nombre Nodo
    Type: ENUM
    Values:
    	Value: valor 1
    	Value: valor 2
    	Value: valor 3

Una implementación conforme DEBE comprobar los tipos ENUM contra sus valores permitidos y DEBE rechazar cualquier valor que no coincida exactamente con uno de ellos.

10. Cardinalidades

Las cardinalidades se expresan mediante los nodos Min y Max dentro de cada Child. Son enteros no negativos opcionales que indican el número mínimo o máximo de apariciones permitidas de ese hijo.

Reglas:

11. Orden de los hijos

STXT Schema no valida el orden de los hijos. La validación de cardinalidad y de presencia es independiente de la posición de cada hijo dentro de su padre: sólo cuenta cuántas veces aparece cada hijo, no en qué orden.

Dos documentos con los mismos hijos en distinto orden validan exactamente igual. Esto es una decisión de diseño coherente con el principio Human-First: el autor de un documento no debería tener que recordar el orden de los campos.

Orden preservado, no validado. Aunque el orden no se valida, el orden de aparición de los hijos se preserva en el árbol parseado (garantía del núcleo, STXT-SPEC). Por tanto, una aplicación que necesite significado posicional (por ejemplo, secciones consecutivas de un documento) lo obtiene del propio árbol, no de la validación. La semántica del orden corresponde a la aplicación.

La validación de orden secuencial es un no-objetivo explícito de STXT Schema: introducir modelos de contenido ordenados (al estilo de xs:sequence) complicaría notablemente los validadores (autómatas, ambigüedad de partículas) sin un beneficio claro para los casos de uso objetivo.

12. Ejemplos Normativos

12.1 Schema con referencias cross-namespace

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: BLOCK

Y en org.example.meta:

Schema (@stxt.schema): org.example.meta
    Node: Metadata
    	Type: INLINE

12.2 Documento válido

Document (com.example.docs):
    Metadata (org.example.meta): info
    Content>>
        Línea 1
        Línea 2

12.3 Estructura recursiva

El modelo cerrado admite recursión sin esfuerzo: un Node puede declararse como hijo de sí mismo o de un ancestro.

Schema (@stxt.schema): com.example.docs
    Node: Section
        Type: GROUP
        Children:
            Child: Title
                Min: 1
                Max: 1
            Child: Section
    Node: Title
        Type: INLINE

Aquí Section puede contener más nodos Section anidados a cualquier profundidad (limitada por el límite de profundidad recomendado en STXT-SPEC, sección de seguridad).

13. Errores de Schema

Un schema es inválido si:

  1. Define dos Node con el mismo nombre canónico.
  2. Usa un Type desconocido.
  3. Define Children en un Node cuyo tipo no admite hijos (sección 9).
  4. La cardinalidad es inválida (Min > Max, valor no entero no negativo, Min/Max duplicados).
  5. Un Node: ENUM no define Values, o Values no contiene ningún Value.
  6. Aparece un Value duplicado tras la normalización inline por trim.
  7. Aparecen dos nodos Child equivalentes (mismo nombre canónico + namespace efectivo) dentro del mismo Children.
  8. Aparece un hijo en Children cuyo Node no está definido en su schema correspondiente.

Un documento es inválido frente a un schema si:

14. Conformidad

Una implementación es conforme si:

15. Schema del Schema (`@stxt.schema`)

Esta sección define el schema oficial del propio sistema de schemas: el meta-schema que valida todos los documentos del namespace @stxt.schema.

Nivel de garantía. El meta-schema valida la forma de un documento schema (qué nodos existen, sus tipos, sus cardinalidades). No puede expresar las reglas condicionales o cruzadas de este documento (por ejemplo "Values sólo si Type: ENUM", o "Min ≤ Max"), que pertenecen al lenguaje pero no al meta-schema. Por tanto, "validar contra el meta-schema" es condición necesaria pero no suficiente para ser un schema válido: además deben cumplirse las reglas de la sección 13.

15.1 Consideraciones

15.2 Meta-Schema completo

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
    Node: Values
        Type: GROUP
        Children:
            Child: Value
                Min: 1
    Node: Value

Nota: en el meta-schema, Node y Child son de tipo por defecto INLINE (su valor inline es el nombre del nodo objetivo o del hijo) y por eso admiten hijos. Esto ilustra que INLINE es el tipo que combina valor y estructura, el núcleo del sistema.

15.3 Lectura rápida

15.4 Ejemplo mínimo válido

Schema (@stxt.schema): com.example.docs
    Node: Document

15.5 Ejemplo completo

Schema (@stxt.schema): com.example.docs
    Description: Schema de ejemplo
    Node: Document
        Type: GROUP
        Children:
        	Child: Title
        		Min: 1
        		Max: 1
        	Child: Author
        	Child: Metadata (org.example.meta)
        		Max: 1
    Node: Title
        Type: INLINE
    Node: Author
        Type: INLINE

16. Fin del Documento