STXT Esquemas (@stxt.schema)
1. Introducción2. 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:
- Es un documento STXT con namespace
@stxt.schema. - Define los nodos, tipos y cardinalidades del namespace objetivo.
- No modifica la sintaxis base de STXT; opera sobre la estructura ya parseada.
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:
- Parseo del documento a una estructura jerárquica STXT.
- Resolución del namespace efectivo de cada nodo.
- 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:
<namespace_objetivo>DEBE ser un namespace válido según STXT-SPEC.- El nodo raíz
SchemaDEBE pertenecer al namespace@stxt.schema. - El documento schema PUEDE incluir un nodo
Description. - El documento schema DEBE incluir uno o más nodos
Node.
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:
- NO DEBE existir más de un schema efectivo simultáneamente.
- Si una implementación dispone de varios schemas candidatos para el mismo namespace, DEBERÍA aplicar una política de selección clara y determinista.
- Para una validación concreta, sólo DEBE existir un único schema efectivo.
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:
- Si un
Nodedeclara un bloqueChildren, sus instancias en el documento sólo PUEDEN tener como hijos directos los nodos declarados medianteChild(cada uno identificado por su par lógiconombre canónico + namespace efectivo). - Si un
Nodeno declaraChildren, sus instancias en el documento NO PUEDEN tener ningún hijo directo (cierre total). - La aparición de un hijo directo no declarado DEBE provocar un error de validación.
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.v1 → com.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:
- El valor inline de
NodeDEBE ser un nombre de nodo válido según STXT-SPEC. - Cada
NodeDEBE ser único dentro del schema a nivel de nombre canónico. - Cada
Nodedefine la semántica del nodo en el namespace objetivo del schema. - Si
Typese omite, el tipo por defecto esINLINE. - Un
NodeNO DEBE contener más de un nodoDescription, más de un nodoType, más de un nodoChildrenni más de un nodoValues. - Sólo los tipos que admiten hijos (ver sección 9) PUEDEN declarar
Children. DeclararChildrenen un tipo que no admite hijos DEBE provocar un error de schema.
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
- Si se omite el namespace, el
Childpertenece al namespace objetivo del schema actual. - Si se indica un namespace explícito, el
Childpertenece a ese namespace concreto. - Dentro de un mismo nodo
Children, una implementación NO DEBE aceptar dos nodosChildque apunten al mismo par lógiconombre canónico + namespace efectivo.
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:
- Si aparece
Child: Metadata (org.example.meta), entonces DEBE existir un schema paraorg.example.metay dentro de él DEBE existirNode: Metadata. - Una implementación PUEDE diferir esta comprobación hasta el momento de validación del documento, pero el schema sigue siendo semánticamente incompleto hasta que dicha definición exista.
9. Tipos
Los tipos definen:
- La forma del valor del nodo (inline, bloque
>>, ambas o ninguna). - Si el nodo admite hijos.
- 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:
- Forma del valor:
INLINE,BLOCK,INLINE/BLOCKoNONE. - Admite hijos: SÍ o NO.
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:
- El tipo NO controla obligatoriedad; sólo forma y validez del valor. La obligatoriedad de aparición se controla mediante cardinalidad.
- El valor de
TypeDEBE coincidir exactamente con uno de los tipos definidos en esta sección. - Declarar
Childrenen unNodecuyo tipo no admite hijos DEBE provocar un error de schema.
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 | SÍ | Texto inline :. Tipo por defecto. Valor opcional sin validación específica. Admite hijos. |
| GROUP | NONE | SÍ | 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. |
| 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:
- La comparación DEBE hacerse sobre el valor inline ya normalizado mediante trim a izquierda y derecha, tal como define STXT-SPEC.
- La comparación DEBE ser exacta y CASE-SENSITIVE.
- La comparación NO DEBE aplicar canonización adicional, eliminación de diacríticos ni normalizaciones equivalentes al nombre canónico de los nodos.
- El nodo DEBE definir
Valuescon nodosValue, que representan los valores permitidos. - Cada
ValueDEBE ser único tras la normalización inline por trim. ENUMno admite hijos: unNodede tipoENUMNO DEBE declararChildren.
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:
- Si
Minse omite, el mínimo efectivo es0. - Si
Maxse omite, el máximo efectivo es ilimitado. MinyMaxNO DEBEN aparecer más de una vez dentro del mismoChild.- Si existen ambos,
MinNO DEBE ser mayor queMax. - La cardinalidad se aplica por instancia del nodo padre.
- La cardinalidad cuenta sólo hijos directos con el mismo nombre canónico y el mismo namespace efectivo.
- La validación de cardinalidad es independiente del orden de los hijos: cuenta apariciones, no posiciones (ver sección 11).
- Una implementación conforme DEBE comprobar las cardinalidades.
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:
- Define dos
Nodecon el mismo nombre canónico. - Usa un
Typedesconocido. - Define
Childrenen unNodecuyo tipo no admite hijos (sección 9). - La cardinalidad es inválida (
Min > Max, valor no entero no negativo,Min/Maxduplicados). - Un
Node: ENUMno defineValues, oValuesno contiene ningúnValue. - Aparece un
Valueduplicado tras la normalización inline por trim. - Aparecen dos nodos
Childequivalentes (mismonombre canónico + namespace efectivo) dentro del mismoChildren. - Aparece un hijo en
ChildrencuyoNodeno está definido en su schema correspondiente.
Un documento es inválido frente a un schema si:
- Un nodo presenta un hijo directo no declarado en el
Childrende su definición (modelo cerrado, sección 6). - Un nodo sin
Childrendeclarado presenta cualquier hijo directo. - Se incumple una cardinalidad declarada.
- El valor de un nodo no cumple la validación de su tipo.
- Un valor
ENUMno coincide exactamente con ninguno de susValue.
14. Conformidad
Una implementación es conforme si:
- Implementa íntegramente este documento.
- Valida tipos, formas de valor, cardinalidades y valores permitidos (ENUM).
- Aplica el modelo de contenido cerrado (sección 6).
- Aplica la regla de compatibilidad de hijos por tipo (sólo
INLINEyGROUPadmiten hijos). - Aplica la regla estricta de definición obligatoria de todos los nodos referenciados en
Children. - Valida cardinalidades de forma independiente del orden.
- Selecciona, para cada validación, un único schema efectivo por namespace.
- Rechaza documentos y schemas inválidos.
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
- Todo documento schema es:
Schema (@stxt.schema): <namespace-objetivo> - Un schema contiene:
- Opcionalmente una
Description. - Uno o más nodos
Node.
- Opcionalmente una
- Cada
Node:- Tiene valor inline (el nombre del nodo del namespace objetivo).
- Puede tener opcionalmente:
DescriptionTypeChildrenValues
- Cada
Child(elemento deChildren) define el nombre (y opcionalmente un namespace distinto) y puede tener:Min: Número mínimo de nodos que deben aparecer. Si no existe el nodo no hay un mínimo establecido.Max: Número máximo de nodos que pueden aparecer. Si no existe el nodo no hay un máximo establecido.
- Cada
Values:- Sólo puede aparecer en nodos
Nodede tipoENUM. - Contiene uno o más nodos
Value.
- Sólo puede aparecer en nodos
- Los nombres (
Schema,Node,Type,Children,Child,Description,Min,Max,Values,Value) pertenecen al namespace@stxt.schema.
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
-
SchemaValor inline = namespace objetivo (ej.com.example.docs). Hijos:Description(?),Node(*). -
NodeValor inline = nombre del nodo objetivo (ej.Document,Autor). Hijos opcionales:Type: tipo concreto (si falta ⇒INLINE).Children: Nodo con listado deChildpermitidos.Description: texto explicativo.Values: Valores permitidos (sólo tipo ENUM).
-
TypeInline (ENUM), con el nombre del tipo (GROUP,INLINE,NUMBER, etc.). -
ChildrenGROUP: contiene uno o más nodosChild. -
DescriptionTEXT: puede ser inline o multiline. -
ValuesGROUP: contiene uno o más nodosValue. -
ValueValor inline con uno de los valores permitidos para elENUM.
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