STXT frente a YAML

YAML y STXT usan la indentación para definir la jerarquía. El modelo mental es distinto: YAML tiene mapas y listas, como JSON, y STXT tiene árboles de nodos de texto, como XML.

El mismo contenido, dos veces

Un descriptor de servicio en YAML:

service: billing
replicas: 2
ports:
  - 8080
  - 8443
maintainer: ana@example.com
notes: |
  Restarted after the 2026-08-31 incident.
  The TLS certificate expires on 2027-03-01.

Y en STXT:

Service: billing
	Replicas: 2
	Ports:
		Port: 8080
		Port: 8443
	Maintainer: ana@example.com
	Notes >>
		Restarted after the 2026-08-31 incident.
		The TLS certificate expires on 2027-03-01.

Un documento sencillo se parece en los dos. Las diferencias son estas:

YAML STXT
Valores El tipo lo decide la grafía: 2 es un entero y "2" una cadena Todo valor es texto. El tipo, si hace falta, lo declara la plantilla
Listas Dos sintaxis: de bloque (- 8080) y de flujo ([8080, 8443]) No hay sintaxis de lista: un hijo repetido es la lista (FAQ)
Indentación Cualquier número de espacios por nivel, y sin tabuladores Un tabulador o cuatro espacios por nivel
Texto de varias líneas Escalares de bloque, con varios indicadores Un nodo block >>
Namespaces No tiene Forman parte del lenguaje (STXT-SPEC §7)
Esquemas Herramientas externas Forman parte del lenguaje, y son opcionales

Cuando la grafía cambia el significado

En YAML, un valor sin comillas se convierte a un tipo según su forma. Las reglas cambiaron entre las versiones 1.1 y 1.2 del lenguaje:

country: NO         # false en YAML 1.1; la cadena "NO" en 1.2
version: 3.10       # el número 3.1 en las dos
window: 12:30       # el entero 750 en YAML 1.1 (sexagesimal); una cadena en 1.2
enabled: yes        # true en 1.1; la cadena "yes" en 1.2

Para conservar NO, 3.10 o 12:30 como texto hay que ponerlos entre comillas. En STXT un valor es siempre los caracteres escritos:

Settings:
	Country: NO
	Version: 3.10
	Window: 12:30
	Enabled: yes
Nombre nodo Valor del nodo
Country NO
Version 3.10
Window 12:30
Enabled yes

Si Enabled debe ser un booleano, lo dice la plantilla (Enabled: (1) BOOLEAN). En ese caso el validador rechaza yes, y no lo convierte.

El texto de varias líneas

Un escalar de bloque de YAML combina varios indicadores: el estilo (| literal o > plegado), el salto de línea final (-, + o ninguno) y, si hace falta, la indentación:

literal: |
  first line
  second line
folded: >
  first line
  second line
kept: |+
  first line

next: value

Cada combinación produce una cadena distinta:

Clave Valor
literal "first line\nsecond line\n"
folded "first line second line\n"
kept "first line\n\n" (conserva la línea vacía que le sigue)

STXT tiene una sola forma, el nodo block. El texto es literal, sin variantes y sin caracteres de escape:

Notes >>
	first line
	second line

Se conservan la indentación adicional y las líneas vacías intermedias. Se descartan los blancos al final de cada línea y las líneas vacías finales (STXT-SPEC §10).

Seguridad

YAML incluye dos características que STXT no tiene:

  • Anclas y alias (&a, *a): un documento pequeño puede expandirse a una estructura enorme en memoria.
  • Etiquetas de tipo (!!python/object, !ruby/object): las específicas de una implementación han permitido instanciar objetos arbitrarios al cargar un documento. De ahí las funciones safe_load de las bibliotecas.

STXT no tiene referencias, anclas, etiquetas, inclusión ni entidades. El parseo es lineal, línea a línea y en una sola pasada (STXT-SPEC §15).

La validación

YAML se valida con herramientas externas, normalmente JSON Schema sobre la estructura ya cargada. En STXT los esquemas forman parte del lenguaje. El descriptor del principio, con namespace:

Service (com.example.deploy): billing
	Replicas: 2
	Port: 8080
	Port: 8443
	Maintainer: ana@example.com
	Notes >>
		The TLS certificate expires on 2027-03-01.

Y la plantilla de su namespace:

Template (@stxt.template): com.example.deploy
	Structure >>
		Service (com.example.deploy):
			Replicas: (1) NATURAL
			Port: (+) NATURAL
			Maintainer: (1) EMAIL
			Notes: (?) TEXT

Aquí no hace falta el contenedor Ports: la cardinalidad (+) ya dice que Port se repite. Un documento con errores no valida:

# ERROR: este documento no valida
Service (com.example.deploy): billing
	# `two` no es un NATURAL
	Replicas: two
	# Falta al menos un `Port`
	# `ana` no es un EMAIL
	Maintainer: ana
	# `Region` no está en la plantilla
	Region: eu-west-1

¿Y TOML?

TOML comparte objetivo con STXT: ficheros que una persona escribe y lee. La jerarquía no está en la indentación, sino en cabeceras que repiten la ruta completa de su tabla:

[[job]]
name = "database"

[[job.step]]
run = "pg_dump acme > acme.sql"

[[job.step]]
run = "gzip acme.sql"

[[job]]
name = "documents"

[[job.step]]
run = "tar cf documents.tar /srv/docs"

Cada [[job.step]] pertenece al último [[job]] abierto. En STXT cada nivel se escribe una vez, y un hijo pertenece al nodo bajo el que está indentado:

Backup:
	Job: database
		Step: pg_dump acme > acme.sql
		Step: gzip acme.sql
	Job: documents
		Step: tar cf documents.tar /srv/docs

Como en YAML, el tipo de un valor lo decide su grafía: 14 es un entero y "14" una cadena. Las cadenas van siempre entre comillas, y las de varias líneas no se pueden sangrar con su tabla. No tiene namespaces ni esquemas.

¿Y NestedText?

NestedText toma varias de las decisiones de STXT: todo valor es texto, sin tipos implícitos ni caracteres de escape, y la estructura está en la indentación. El descriptor del principio:

service: billing
replicas: 2
ports:
    - 8080
    - 8443
maintainer: ana@example.com
notes:
    > Restarted after the 2026-08-31 incident.
    > The TLS certificate expires on 2027-03-01.

Y en STXT:

Service: billing
	Replicas: 2
	Ports:
		Port: 8080
		Port: 8443
	Maintainer: ana@example.com
	Notes >>
		Restarted after the 2026-08-31 incident.
		The TLS certificate expires on 2027-03-01.

2 y 8080 son cadenas en los dos, y el texto de varias líneas es literal: en NestedText cada línea empieza por >, y en STXT va bajo un nodo block.

NestedText conserva el modelo de datos de YAML (diccionarios, listas y cadenas), y deja los tipos y la validación a la aplicación. No tiene namespaces ni esquemas.