STXT Transform

Estado:
Genesis
última modificación:
2026-10-12

1. Introducción

Este documento es STXT-TRANSFORM-SPEC; las demás especificaciones lo citan con ese nombre.

Este documento define STXT Transform: las operaciones que llevan el contenido de un documento STXT a otro formato de datos, lo traen desde él y lo completan con datos externos. Son tres:

Operación Entrada Salida
Exportación (export) Un documento STXT El mismo contenido en otro formato: JSON, YAML, XML
Importación (import) Un documento en otro formato El mismo contenido como documento STXT
Relleno (fill) Un documento STXT con Slots y unos datos Un documento STXT completo

Un Slot es el lugar de un documento que espera un dato. El relleno pone en cada Slot el dato que le corresponde.

Su propósito es que un documento STXT pueda ser la fuente de los programas que ya leen JSON, YAML o XML, y que los datos que ya existen en esos formatos puedan pasar a STXT, sin escribir una conversión propia para cada namespace.

La exportación y la importación se apoyan en la definición del namespace del documento, sea un schema o un template. El texto de un documento no dice qué valor es un número, qué nodo es una lista ni cómo se llaman sus elementos: lo dice su definición. Por eso estas dos operaciones apenas necesitan más información que el documento y su definición, y por eso mismo esta especificación exige para ellas, de momento, que el documento tenga namespace y que ese namespace tenga definición.

El relleno no necesita definición ni namespace: lo que hace cada Slot está escrito en el propio documento.

Esta especificación no cambia la sintaxis de STXT-SPEC ni la validación de STXT-SCHEMA-SPEC: es una capa posterior al parseo y a la validación, y opcional como ellas.

1.1 Fecha y estado de esta especificación

Esta especificación lleva su propia fecha y su propio estado en los campos Last modif y Status de su Metadata, independientes de los de las demás especificaciones de STXT y con el significado que fija STXT-SPEC §1.1. Está en Genesis: en construcción, y cualquier parte de ella puede cambiar sin aviso. Depende de STXT-SPEC y de STXT-SCHEMA-SPEC.

Hoy contiene la presentación de las tres operaciones y dos ejemplos: la exportación y la importación con JSON, y un primer esbozo del relleno de Slots. Las reglas de cada formato y las de los Slots están por escribir.

1.2 Relación con el árbol canónico

STXT-TREE-SPEC ya define una representación JSON de un documento: el árbol canónico. Su propósito es otro. El árbol canónico describe el resultado del parseo, con cada nodo como un objeto que lleva su nombre, su nombre canónico, su namespace, su forma y su valor, y existe para comparar implementaciones. No necesita definición, y todos los valores son texto.

La exportación de esta especificación produce el JSON que escribiría quien diseñara ese dato directamente en JSON: objetos con una clave por nodo, arrays, números y booleanos. Necesita la definición, y es la forma pensada para que la consuma un programa.

1.3 Relación con los templates

Un documento con Slots no es un @stxt.template. Un template (STXT-TEMPLATE-SPEC) describe la estructura de todos los documentos de un namespace y sirve para validarlos. Un documento con Slots es un documento, con namespace o sin él, al que le faltan valores: sus Slots se rellenan con unos datos externos, por ejemplo un JSON, y el resultado es un documento completo, que se valida como cualquier otro.

Para evitar la confusión, esta especificación no llama «plantilla» ni «template» al documento con Slots.

2. Terminología

Las palabras clave "DEBE", "NO DEBE", "DEBERÍA", "NO DEBERÍA", y "PUEDE" deben interpretarse según RFC 2119 y RFC 8174: tienen ese significado únicamente cuando aparecen en mayúsculas, como aquí.

Términos como nodo, namespace, schema, template, tipo y cardinalidad mantienen su significado en STXT-SPEC, STXT-SCHEMA-SPEC y STXT-TEMPLATE-SPEC.

Definiciones adicionales:

  • Definición: el schema o el template del namespace de un documento, como en STXT-DISCOVERY-SPEC.
  • Formato externo: un formato de datos distinto de STXT, como JSON, YAML o XML.
  • Exportación: la operación que produce, a partir de un documento STXT y su definición, un documento en un formato externo.
  • Importación: la operación que produce, a partir de un documento en un formato externo y una definición, un documento STXT.
  • Slot: el lugar de un documento STXT que el relleno sustituye por un dato.
  • Documento con Slots: un documento STXT que contiene uno o más Slots.
  • Relleno: la operación que produce un documento STXT completo a partir de un documento con Slots y unos datos.

3. Un ejemplo: STXT y JSON

Esta sección no es normativa. Muestra la dirección de la exportación y la importación con el formato más sencillo.

Un documento:

# El servidor web de la oficina
Servidor (com.example.servidores):
	Nombre: web-01
	Activo: true
	Puertos:
		Puerto: 80
		Puerto: 443
	Responsable:
		Persona: Ana Ruiz
		Correo: ana@example.com
	Notas >>
		Reiniciar tras cada despliegue.
		No apagar en horario de oficina.

Y la definición de su namespace, aquí un template:

Template (@stxt.template): com.example.servidores
	Structure >>
		Servidor (com.example.servidores): GROUP
			Nombre: (1)
			Activo: (1) BOOLEAN
			Puertos: (1) GROUP
				Puerto: (+) NATURAL
			Responsable: (?) GROUP
				Persona: (1)
				Correo: (1) EMAIL
			Notas: (?) TEXT

3.1 Exportación

La exportación del documento a JSON:

{
	"Nombre": "web-01",
	"Activo": true,
	"Puertos": [80, 443],
	"Responsable": {
		"Persona": "Ana Ruiz",
		"Correo": "ana@example.com"
	},
	"Notas": "Reiniciar tras cada despliegue.\nNo apagar en horario de oficina."
}

Lo que decide la definición:

En el documento En la definición En JSON
Nombre: web-01 Sin tipo Un string
Activo: true BOOLEAN Un booleano
Puerto: 80 NATURAL Un número
Puertos, con dos Puerto GROUP con un solo hijo, que se repite Un array. El nombre Puerto no aparece
Responsable, con dos hijos GROUP con hijos distintos Un objeto, con una clave por hijo
Notas >> TEXT Un string, con las líneas separadas por \n
  • Sin definición, 80 y true serían texto, y nada distinguiría una lista de un nodo con un solo hijo.
  • El comentario no se exporta: no forma parte del árbol del documento.
  • El nodo raíz no aparece: el JSON es el contenido de Servidor.

Como contraste, el nodo Puertos en el árbol canónico de STXT-TREE-SPEC, que en la exportación es [80, 443]:

{
	"name": "Puertos",
	"canonicalName": "puertos",
	"namespace": "com.example.servidores",
	"form": "inline",
	"value": "",
	"children": [
		{
			"name": "Puerto",
			"canonicalName": "puerto",
			"namespace": "com.example.servidores",
			"form": "inline",
			"value": "80",
			"children": []
		},
		{
			"name": "Puerto",
			"canonicalName": "puerto",
			"namespace": "com.example.servidores",
			"form": "inline",
			"value": "443",
			"children": []
		}
	]
}

3.2 Importación

La importación es el camino inverso. Recibe el JSON anterior y el nodo raíz que debe producir, Servidor (com.example.servidores), y devuelve este documento:

Servidor (com.example.servidores):
	Nombre: web-01
	Activo: true
	Puertos:
		Puerto: 80
		Puerto: 443
	Responsable:
		Persona: Ana Ruiz
		Correo: ana@example.com
	Notas >>
		Reiniciar tras cada despliegue.
		No apagar en horario de oficina.

La definición aporta lo que el JSON no lleva:

  • El nombre Puerto de cada elemento del array Puertos.
  • El namespace de cada nodo.
  • La forma de cada nodo: Notas se escribe como bloque >> porque su texto tiene más de una línea y TEXT admite las dos formas.

El documento importado tiene el mismo árbol que el original. Solo se ha perdido el comentario.

4. Un ejemplo: relleno de Slots

Esta sección no es normativa. Es un primer esbozo de los Slots y de cómo se combinan.

Un documento con Slots:

Pedido (com.example.pedidos): $numero$
	Fecha: $fecha$
	Moneda: EUR
	Cliente: {cliente}
		Nombre: $nombre$
		Correo: $correo$
		# El teléfono es opcional
		Teléfono: ?$telefono$
	Línea: [lineas]$producto$
		Cantidad: $cantidad$
		Precio: $precio$
		Nota: ?$nota$
	Envío: [envios]
		Transportista: $transportista$
		Bulto: [bultos]

Los datos, en JSON:

{
	"numero": "2026-0142",
	"fecha": "2026-10-12",
	"cliente": {
		"nombre": "Librería Atenea",
		"correo": "pedidos@atenea.example"
	},
	"lineas": [
		{ "producto": "Cuaderno A5", "cantidad": 40, "precio": 3.25, "nota": "Tapa azul" },
		{ "producto": "Lápiz HB", "cantidad": 200, "precio": 0.45 }
	],
	"envios": [
		{ "transportista": "Correos", "bultos": ["C-01", "C-02"] },
		{ "transportista": "MRW", "bultos": ["M-07"] }
	]
}

Y el documento que produce el relleno:

Pedido (com.example.pedidos): 2026-0142
	Fecha: 2026-10-12
	Moneda: EUR
	Cliente:
		Nombre: Librería Atenea
		Correo: pedidos@atenea.example
	Línea: Cuaderno A5
		Cantidad: 40
		Precio: 3.25
		Nota: Tapa azul
	Línea: Lápiz HB
		Cantidad: 200
		Precio: 0.45
	Envío:
		Transportista: Correos
		Bulto: C-01
		Bulto: C-02
	Envío:
		Transportista: MRW
		Bulto: M-07

Los Slots del ejemplo:

Slot Qué hace En el ejemplo
$var$ Pone el valor del dato var Fecha: $fecha$
{objeto} Entra en el objeto objeto: los Slots del nodo y de sus hijos se buscan dentro de él Cliente: {cliente}
[lista] Repite el nodo, con sus hijos, una vez por cada elemento del array lista Línea, Envío, Bulto
? delante Hace opcional el Slot: si el dato no existe, el nodo no aparece Teléfono: ?$telefono$
  • Si el elemento de un array es un objeto, el relleno entra en él: cada Envío busca su transportista y sus bultos en su propio elemento.
  • Si el elemento es un valor, es el valor del nodo: Bulto: [bultos] produce Bulto: C-01 y Bulto: C-02.
  • Un nodo puede combinar Slots: Línea: [lineas]$producto$ repite el nodo y pone en cada uno su producto. Primero se evalúa [lista], después {objeto} y por último $var$.
  • Un valor sin Slots se copia tal cual: Moneda: EUR.
  • Todo Slot es obligatorio, sea $var$, {objeto} o [lista], salvo que lleve ? delante: si faltara cantidad en una línea, o cliente en los datos, el relleno fallaría.
  • Teléfono no aparece porque el cliente no tiene telefono. Nota aparece en la primera Línea y no en la segunda.
  • Un array vacío no produce ningún nodo y no es un error del relleno. Si el nodo era obligatorio, lo dirá la validación del documento rellenado.
  • Un dato que no encaja con su Slot es un error: un objeto donde $var$ espera un valor, o un valor donde [lista] espera un array.
  • El comentario no pasa al documento rellenado.
  • Un documento con Slots no se valida. El que se valida es siempre el documento rellenado.