Curso de XML para TEI
De la sintaxis XML al marcado filológico, el aparato crítico, la consulta con XPath y la publicación de ediciones digitales
Cómo usar este documento
Este material reúne doce lecciones progresivas, de la sintaxis XML más elemental hasta la publicación de ediciones TEI. Cada lección sigue la misma estructura:
- un Objetivo breve;
- el desarrollo de los conceptos, numerados internamente;
- ejercicios y soluciones (las soluciones aparecen en un bloque plegable: inténtalo antes de mirarlas);
- avisos sobre errores frecuentes;
- un resumen de qué debes retener;
- una tarea final.
Algunas lecciones incluyen además un bloque de código de práctica en Python (con lxml para las lecciones de XPath y transformación). Estas celdas son opcionales: no sustituyen a un editor XML como Oxygen, pero permiten manipular los mismos ejemplos en Google Colab, Jupyter o un chunk ejecutable de Quarto/RStudio.
Recomendaciones de trabajo:
- Lee cada lección en orden; las lecciones 7 a 12 dan por hecho lo aprendido en las lecciones 1 a 6.
- Resuelve los ejercicios antes de abrir la solución.
- Comprueba siempre tus archivos en Oxygen (o en otro editor/validador XML): primero la buena formación, después la validez TEI.
- Usa la hoja de referencia rápida del final como chuleta de consulta mientras trabajas.
Lección 1: Introducción a XML para empezar con TEI
Al terminar esta lección entenderás qué es XML, cómo piensa un documento marcado y cómo crear un archivo mínimo sin errores de estructura.
Idea central
XML no sirve para dar formato visual, sino para representar la estructura y el significado de la información mediante etiquetas.
En TEI, eso significa que no marcas “esto va en cursiva”, sino “esto es un verso”, “esto es un título”, “esto es un nombre de persona” o “esto es una abreviatura”.
Conceptos básicos
- Elemento: una unidad marcada con apertura y cierre, por ejemplo
<titulo>Parzival</titulo>. - Atributo: información añadida dentro de la etiqueta de apertura, por ejemplo
<verso n="12">...</verso>. - Elemento raíz: el contenedor único de todo el documento.
- Texto: el contenido entre etiquetas.
- Jerarquía: relación padre-hijo entre elementos.
Ejemplo mínimo
<poema>
<titulo>Iwein</titulo>
<autor>Hartmann von Aue</autor>
</poema>Aquí poema es la raíz, y titulo y autor son hijos de poema.
Cómo leer XML
Piensa en XML como un árbol. En vez de mirar la página como lector final, la miras como editor de datos textuales: qué partes tiene el texto y qué función cumple cada una.
Por ejemplo, un poema puede descomponerse en obra, autor, estrofa y verso; XML permite declarar esas partes explícitamente para que luego puedan validarse, buscarse o transformarse.
Ejemplo algo más rico
<poema>
<titulo>Erec</titulo>
<autor>Hartmann von Aue</autor>
<estrofa>
<verso n="1">Uns ist in alten maeren</verso>
<verso n="2">wunders vil geseit</verso>
</estrofa>
</poema>Eso todavía no es TEI, pero ya piensa como TEI: estructura textual antes que apariencia.
Reglas mínimas
Estas reglas no se negocian en XML bien formado:
- Toda etiqueta abierta debe cerrarse.
- Las etiquetas distinguen mayúsculas y minúsculas.
- Los elementos deben anidarse correctamente.
- Debe haber un solo elemento raíz.
- Los atributos van siempre entre comillas.
Incorrecto:
<poema>
<titulo>Iwein<título>
<autor>Hartmann von Aue</autor>
</poema>Incorrecto también:
<poema>
<estrofa>
<verso>Texto</estrofa>
</verso>
</poema>Correcto:
<poema>
<estrofa>
<verso>Texto</verso>
</estrofa>
</poema>Diferencia útil
“Bien formado” no significa todavía “válido”. Un XML bien formado solo cumple las reglas sintácticas generales; un XML válido además cumple las reglas de un esquema concreto, como una DTD o un esquema TEI.
Copia este texto en un archivo llamado poema.xml:
<?xml version="1.0" encoding="UTF-8"?>
<poema>
<titulo>Der arme Heinrich</titulo>
<autor>Hartmann von Aue</autor>
<estrofa>
<verso n="1">Ein ritter sô gelêret was</verso>
<verso n="2">daz er an den buochen las</verso>
</estrofa>
</poema>Código de práctica (Python)
Estas celdas son opcionales: no sustituyen a Oxygen, pero permiten manipular los mismos ejemplos como texto dentro de un cuaderno Jupyter, Colab o un chunk de Quarto/RStudio.
xml_ejemplo_1 = '''<?xml version="1.0" encoding="UTF-8"?>
<poema>
<titulo>Der arme Heinrich</titulo>
<autor>Hartmann von Aue</autor>
<estrofa>
<verso n="1">Ein ritter sô gelêret was</verso>
<verso n="2">daz er an den buochen las</verso>
</estrofa>
</poema>'''
print(xml_ejemplo_1)Responde:
- ¿Cuál es el elemento raíz?
- ¿Qué elementos son hijos directos de
<poema>? - ¿Qué elemento tiene un atributo?
- ¿Cuál es el nombre del atributo?
- ¿Cuál es su valor?
- La raíz es
<poema>. - Sus hijos directos son
<titulo>,<autor>y<estrofa>. - El elemento con atributo es
<verso>. - El atributo se llama
n. - Sus valores son
"1"y"2".
- Cerrar mal una etiqueta.
- Mezclar mayúsculas y minúsculas.
- Olvidar comillas en un atributo.
- Cruzar etiquetas por mala anidación.
Corrige este XML para que quede bien formado:
<poema>
<titulo>Erec</titulo>
<autor>Hartmann von Aue</autor>
<estrofa>
<verso n=1>Des was ein ritter wol bekant
<verso n="2">an im was manegiu tugent</verso>
</estrofa>
</poema><poema>
<titulo>Erec</titulo>
<autor>Hartmann von Aue</autor>
<estrofa>
<verso n="1">Des was ein ritter wol bekant</verso>
<verso n="2">an im was manegiu tugent</verso>
</estrofa>
</poema>XML no describe cómo se ve un texto, sino qué es cada parte del texto.
Eso es exactamente lo que luego hará TEI, pero con un vocabulario académico más rico para describir documentos, textos, metadatos y fenómenos editoriales.
- Escribe un XML propio de 8 a 10 líneas con raíz, título, autor y dos versos.
- Introduce a propósito un error y comprueba si lo detectas.
- Ábrelo en Oxygen o en otro editor XML y revisa si está bien formado.
Lección 2: Sintaxis XML sin errores
En esta lección aprenderás a escribir XML sin errores de sintaxis. La meta es que puedas crear archivos bien formados de manera segura antes de pasar a la codificación propiamente TEI.
1. Qué significa escribir XML correctamente
Un documento XML correcto en el nivel más básico es un documento bien formado. Eso significa que respeta las reglas generales de sintaxis: un único elemento raíz, etiquetas cerradas, anidación correcta, coincidencia exacta entre apertura y cierre, y valores de atributos entre comillas.
Todavía no significa que sea TEI válido. Solo significa que el documento no está roto.
2. Las reglas obligatorias
Regla 1. Debe existir un único elemento raíz
Todo el documento debe quedar contenido dentro de un único elemento principal.
<poema>
<titulo>Iwein</titulo>
<autor>Hartmann von Aue</autor>
</poema>Incorrecto:
<titulo>Iwein</titulo>
<autor>Hartmann von Aue</autor>Regla 2. Toda etiqueta abierta debe cerrarse
Correcto:
<titulo>Erec</titulo>Incorrecto:
<titulo>ErecRegla 3. Las etiquetas son sensibles a mayúsculas y minúsculas
Correcto:
<verso>Texto</verso>Incorrecto:
<verso>Texto</Verso>Regla 4. Los elementos deben anidarse bien
Correcto:
<estrofa>
<verso>Texto</verso>
</estrofa>Incorrecto:
<estrofa>
<verso>Texto</estrofa>
</verso>La regla práctica es simple: el último elemento que abres debe ser el primero que cierras.
Regla 5. Los atributos deben ir siempre entre comillas
Correcto:
<verso n="1">Uns ist in alten maeren</verso>Incorrecto:
<verso n=1>Uns ist in alten maeren</verso>3. Atributos: qué son y cómo usarlos
Un atributo añade información al elemento, pero no sustituye el contenido.
<verso n="2">wunders vil geseit</verso>Aquí: - verso es el nombre del elemento. - n es el nombre del atributo. - "2" es el valor del atributo. - wunders vil geseit es el contenido textual.
4. Caracteres especiales
En XML, algunos caracteres tienen significado estructural. Si quieres que aparezcan como texto, debes escaparlos.
<se escribe como<&se escribe como&>puede escribirse como>"puede escribirse como"'puede escribirse como'
Código de práctica (Python)
Estas celdas son opcionales: no sustituyen a Oxygen, pero permiten manipular los mismos ejemplos como texto dentro de un cuaderno Jupyter, Colab o un chunk de Quarto/RStudio.
nota_incorrecta = '<nota>2 < 3 y A & B</nota>'
nota_correcta = '<nota>2 < 3 y A & B</nota>'
print('Incorrecto:')
print(nota_incorrecta)
print()
print('Correcto:')
print(nota_correcta)5. Declaración XML
Muchos archivos XML empiezan con una declaración como esta:
<?xml version="1.0" encoding="UTF-8"?>Si la usas, debe ir al principio del archivo. UTF-8 es la codificación más habitual y recomendable.
6. Sangrado y espacios
El sangrado no cambia la estructura lógica del XML, pero ayuda muchísimo a leerlo.
<poema><estrofa><verso n="1">Texto</verso></estrofa></poema><poema>
<estrofa>
<verso n="1">Texto</verso>
</estrofa>
</poema>La segunda forma es mucho más legible.
Esto está mal pensado:
<cursiva>Parzival</cursiva>si lo que quieres decir en realidad es que eso es un título.
Esto está mejor:
<titulo>Parzival</titulo>8. Diagnóstico de errores frecuentes
Error A. Falta de cierre
<poema>
<titulo>Iwein</titulo>
<autor>Hartmann von Aue
</poema>Error B. Cruce de etiquetas
<poema>
<estrofa>
<verso>Texto</estrofa>
</verso>
</poema>Error C. Atributo sin comillas
<verso n=4>Texto</verso>Error D. Dos raíces
<titulo>Erec</titulo>
<autor>Hartmann von Aue</autor>Corrige este XML:
<?xml version="1.0" encoding="UTF-8"?>
<poema>
<titulo>Erec</titulo>
<autor>Hartmann von Aue</autor>
<estrofa>
<verso n=1>Des was ein ritter wol bekant</verso>
<verso n="2">an im was manegiu tugent
</estrofa>
</poema><?xml version="1.0" encoding="UTF-8"?>
<poema>
<titulo>Erec</titulo>
<autor>Hartmann von Aue</autor>
<estrofa>
<verso n="1">Des was ein ritter wol bekant</verso>
<verso n="2">an im was manegiu tugent</verso>
</estrofa>
</poema>Determina cuáles de estos ejemplos son correctos y cuáles no.
A.
<l n="1">Texto</l>B.
<l n="1">Texto</L>C.
<lg>
<l>Uno</l>
<l>Dos</l>
</lg>D.
<lg>
<l>Uno</lg>
<l>Dos</l>- A: correcto.
- B: incorrecto, porque
lyLno son lo mismo. - C: correcto.
- D: incorrecto, porque hay mala anidación y además queda roto el conjunto.
11. Aplicación a TEI
Antes de aprender elementos TEI concretos como <TEI>, <teiHeader>, <text>, <body>, <div> o <l>, necesitas dominar estas reglas mecánicas. Si la sintaxis XML falla, el documento no se puede procesar bien.
Quédate con estas cinco comprobaciones rápidas:
- ¿Tengo una sola raíz?
- ¿He cerrado todo lo que abro?
- ¿He respetado mayúsculas y minúsculas?
- ¿He anidado bien los elementos?
- ¿Están los atributos entre comillas?
- Escribe un archivo XML de 10 a 12 líneas con un poema, dos versos y un atributo
nen cada verso. - Añade una nota con una comparación matemática, por ejemplo
2 < 5, y corrígela usando entidades XML. - Ábrelo en Oxygen y localiza cualquier error de sintaxis.
- Guarda una segunda versión con un error intencionado y explica cuál es.
Bloque de práctica opcional en Python
Estas celdas no sustituyen a Oxygen, pero te permiten guardar ejemplos XML como texto dentro del cuaderno.
xml_practica = '''<?xml version="1.0" encoding="UTF-8"?>
<poema>
<titulo>Práctica</titulo>
<autor>Tu nombre</autor>
<estrofa>
<verso n="1">Primer verso</verso>
<verso n="2">Segundo verso</verso>
</estrofa>
</poema>'''
with open('practica.xml', 'w', encoding='utf-8') as f:
f.write(xml_practica)
print('Archivo guardado como practica.xml')Lección 3: Primer documento TEI
En esta lección aprenderás la estructura mínima de un documento TEI completo. La meta es que pases de XML genérico a un archivo ya reconocible como TEI.
1. La idea central
Un documento TEI no es solo texto marcado: también incluye metadatos sobre ese texto.
Por eso, un documento TEI básico tiene dos grandes partes:
<teiHeader>: contiene los metadatos.<text>: contiene el texto codificado.
2. Estructura mínima
La forma más básica de un documento TEI es esta:
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title>Erec</title>
<author>Hartmann von Aue</author>
</titleStmt>
<publicationStmt>
<p>Edición de trabajo para aprendizaje TEI.</p>
</publicationStmt>
<sourceDesc>
<p>Transcripción de ejemplo basada en un testimonio medieval.</p>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<p>Texto de prueba.</p>
</body>
</text>
</TEI>3. Qué hace cada parte
<TEI>
Es el elemento raíz del documento TEI. Todo queda contenido dentro de él.
<teiHeader>
Describe el archivo: qué es, quién lo ha preparado, cómo se publica y de dónde procede el texto.
<fileDesc>
Es la descripción básica del archivo.
Dentro de <fileDesc> aparecen tres componentes muy importantes:
<titleStmt>: título y responsables.<publicationStmt>: publicación o difusión del archivo.<sourceDesc>: descripción de la fuente.
<text>
Contiene el texto propiamente dicho.
<body>
Es el cuerpo principal del texto.
4. Cómo leer este modelo
Piensa así:
<teiHeader>= información sobre el documento.<text>= contenido del documento.
Es decir, TEI separa metadatos y texto.
5. Ejemplo comentado
Si codificas un fragmento de Iwein, el archivo TEI no solo debe incluir los versos o párrafos, sino también una descripción mínima de qué obra es y cuál es su fuente.
Por eso incluso un archivo TEI muy sencillo ya tiene una dimensión bibliográfica y editorial.
Un error muy habitual al empezar con TEI es escribir solo esto:
<text>
<body>
<p>Texto de prueba</p>
</body>
</text>Eso puede parecer suficiente, pero no constituye un documento TEI completo, porque falta el elemento raíz <TEI> y falta el <teiHeader>.
Transforma este XML genérico:
<poema>
<titulo>Erec</titulo>
<autor>Hartmann von Aue</autor>
<verso>Uns ist in alten maeren</verso>
</poema>en un documento TEI mínimo.
<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title>Erec</title>
<author>Hartmann von Aue</author>
</titleStmt>
<publicationStmt>
<p>Documento de práctica.</p>
</publicationStmt>
<sourceDesc>
<p>Fragmento de prueba para aprendizaje TEI.</p>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<p>Uns ist in alten maeren</p>
</body>
</text>
</TEI>Quédate con esta plantilla mental:
<TEI>envuelve todo.<teiHeader>describe.<text>contiene.<body>desarrolla el texto.
- Crea un documento TEI mínimo con una obra medieval de tu elección.
- Cambia el contenido de
<titleStmt>,<publicationStmt>y<sourceDesc>. - Añade dos párrafos dentro de
<body>.
Lección 4: Estructura del texto en TEI
En esta lección aprenderás a organizar el texto dentro de TEI. La meta es que sepas marcar divisiones, encabezados, párrafos y versos.
1. Del contenedor al contenido
En la lección anterior viste la carcasa general del documento TEI.
Ahora toca organizar el texto interno.
Dentro de <text> normalmente trabajarás con:
<body>para el cuerpo principal.<div>para divisiones o secciones.<head>para encabezados.<p>para párrafos.<lg>para grupos de versos.<l>para versos individuales.
2. Divisiones del texto
El elemento <div> sirve para marcar una subdivisión del texto.
Puede representar, por ejemplo:
- una parte,
- un capítulo,
- una sección,
- un poema,
- una escena.
Ejemplo:
<text>
<body>
<div type="chapter" n="1">
<head>Primer capítulo</head>
<p>Este es el primer párrafo.</p>
<p>Este es el segundo párrafo.</p>
</div>
</body>
</text>3. El elemento <head>
<head> se usa para encabezados o títulos internos.
No describe todo el documento, sino una unidad concreta dentro de él.
Por ejemplo, el título de un capítulo o de una sección.
4. Prosa en TEI
Cuando el texto es prosa, la unidad básica suele ser <p>.
Ejemplo:
<text>
<body>
<div type="prologue">
<head>Prólogo</head>
<p>Este es el primer párrafo del prólogo.</p>
<p>Este es el segundo párrafo del prólogo.</p>
</div>
</body>
</text>5. Verso en TEI
Cuando trabajas con poesía o textos versificados, TEI usa:
<lg>para un grupo de versos.<l>para cada verso.
Ejemplo:
<text>
<body>
<div type="poem">
<head>Erec</head>
<lg type="stanza">
<l n="1">Uns ist in alten maeren</l>
<l n="2">wunders vil geseit</l>
<l n="3">von helden lobebaeren</l>
<l n="4">von grôzer arebeit</l>
</lg>
</div>
</body>
</text>6. Diferencia entre <p> y <l>
No debes usar <p> para versos ni <l> para prosa.
La elección del elemento depende de la naturaleza textual de la unidad que estás codificando.
- Prosa:
<p> - Verso:
<l> - Grupo de versos:
<lg>
7. Combinar estructura y género textual
Puedes tener un documento con divisiones generales y, dentro de ellas, prosa o verso.
Por ejemplo:
<text>
<body>
<div type="introduction">
<head>Introducción</head>
<p>Texto introductorio en prosa.</p>
</div>
<div type="poem">
<head>Poema</head>
<lg type="stanza">
<l n="1">Primer verso</l>
<l n="2">Segundo verso</l>
</lg>
</div>
</body>
</text>Un error común es usar etiquetas genéricas sin reflejar la estructura real.
Por ejemplo, esto es pobre desde el punto de vista TEI:
<texto>
<seccion>
<titulo>Poema</titulo>
<linea>Verso 1</linea>
<linea>Verso 2</linea>
</seccion>
</texto>Está bien como XML inventado, pero no aprovecha el vocabulario TEI.
9. Reescritura en TEI
Una versión TEI sería:
<text>
<body>
<div type="poem">
<head>Poema</head>
<lg>
<l n="1">Verso 1</l>
<l n="2">Verso 2</l>
</lg>
</div>
</body>
</text>Quédate con esta lógica:
<div>organiza grandes bloques.<head>nombra esos bloques.<p>marca prosa.<lg>agrupa versos.<l>marca cada verso.
- Crea una
<div>con<head>y dos<p>. - Crea otra
<div>con un<lg>y cuatro<l>. - Integra ambas en un mismo
<body>.
Código de práctica (Python)
Estas celdas son opcionales: no sustituyen a Oxygen, pero permiten manipular los mismos ejemplos como texto dentro de un cuaderno Jupyter, Colab o un chunk de Quarto/RStudio.
tei_minimo = '''<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title>Iwein</title>
<author>Hartmann von Aue</author>
</titleStmt>
<publicationStmt>
<p>Documento de práctica para aprender TEI.</p>
</publicationStmt>
<sourceDesc>
<p>Fragmento de prueba codificado manualmente.</p>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<p>Este es un texto mínimo en TEI.</p>
</body>
</text>
</TEI>'''
print(tei_minimo)with open("tei_minimo_leccion3.xml", "w", encoding="utf-8") as f:
f.write(tei_minimo)
print("Archivo guardado como tei_minimo_leccion3.xml")tei_estructura_texto = '''<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title>Erec</title>
<author>Hartmann von Aue</author>
</titleStmt>
<publicationStmt>
<p>Práctica de estructura textual en TEI.</p>
</publicationStmt>
<sourceDesc>
<p>Ejemplo didáctico para aprender a usar div, p, lg y l.</p>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<div type="introduccion">
<head>Introducción</head>
<p>Este bloque representa una sección en prosa.</p>
<p>Puede contener uno o varios párrafos.</p>
</div>
<div type="poem">
<head>Pasaje en verso</head>
<lg type="stanza">
<l n="1">Uns ist in alten maeren</l>
<l n="2">wunders vil geseit</l>
<l n="3">von helden lobebaeren</l>
<l n="4">von grôzer arebeit</l>
</lg>
</div>
</body>
</text>
</TEI>'''
print(tei_estructura_texto)
with open("tei_estructura_leccion4.xml", "w", encoding="utf-8") as f:
f.write(tei_estructura_texto)
print("Archivo guardado como tei_estructura_leccion4.xml")Lección 5: Hacer bien el teiHeader
En esta lección aprenderás a construir correctamente el teiHeader de un documento TEI. La meta es que tus archivos no solo contengan texto, sino también una descripción académica mínima y útil.
1. Qué es el teiHeader
El teiHeader es la parte del documento TEI que contiene los metadatos.
No codifica el contenido textual en sí, sino información sobre el archivo, su preparación, su publicación y su fuente.
Dicho de otro modo:
<text>contiene el texto.<teiHeader>describe el texto y el archivo.
2. La pieza central: fileDesc
Dentro del teiHeader, el elemento más importante para empezar es <fileDesc>.
Es la descripción básica del archivo TEI.
En un nivel inicial, debes pensar en fileDesc como una ficha mínima del documento.
3. Los tres bloques que debes dominar
Dentro de <fileDesc> hay tres elementos que debes aprender muy bien:
<titleStmt><publicationStmt><sourceDesc>
<titleStmt>
Aquí indicas el título de la obra y las personas responsables.
Puede incluir, por ejemplo:
<title><author><editor><respStmt>
Ejemplo:
<titleStmt>
<title>Iwein</title>
<author>Hartmann von Aue</author>
<respStmt>
<resp>Codificación TEI</resp>
<name>Tu nombre</name>
</respStmt>
</titleStmt><publicationStmt>
Aquí describes la publicación o difusión del archivo digital.
Para una práctica inicial, un párrafo simple basta.
Ejemplo:
<publicationStmt>
<p>Archivo TEI creado con fines docentes y de aprendizaje.</p>
</publicationStmt>Más adelante podrás añadir editor institucional, licencia, fecha o disponibilidad.
<sourceDesc>
Aquí explicas de dónde procede el texto codificado.
Este punto es muy importante en filología y edición crítica, porque documenta la fuente.
Ejemplo simple:
<sourceDesc>
<p>Transcripción de práctica basada en una edición moderna del texto.</p>
</sourceDesc>4. Plantilla mínima funcional
<teiHeader>
<fileDesc>
<titleStmt>
<title>Erec</title>
<author>Hartmann von Aue</author>
<respStmt>
<resp>Codificación TEI</resp>
<name>Tu nombre</name>
</respStmt>
</titleStmt>
<publicationStmt>
<p>Documento de práctica para aprender TEI.</p>
</publicationStmt>
<sourceDesc>
<p>Fragmento de trabajo basado en una fuente textual identificada por el editor.</p>
</sourceDesc>
</fileDesc>
</teiHeader>5. Qué debes escribir en cada parte
Piensa en estas preguntas:
Para titleStmt
- ¿Cuál es el título de la obra?
- ¿Quién es el autor?
- ¿Quién ha hecho la codificación o edición?
Para publicationStmt
- ¿Qué es este archivo?
- ¿Se ha hecho para docencia, investigación o publicación?
- ¿Hay alguna nota de distribución o uso?
Para sourceDesc
- ¿De dónde sale el texto?
- ¿Es una edición impresa?
- ¿Es una transcripción propia?
- ¿Es un manuscrito, una edición digital o una adaptación de trabajo?
Un error muy común es escribir un teiHeader demasiado pobre, por ejemplo:
<teiHeader>
<fileDesc>
<titleStmt>
<title>Texto</title>
</titleStmt>
</fileDesc>
</teiHeader>Eso no basta, porque deja fuera información clave sobre publicación y fuente.
7. Versión mejorada
<teiHeader>
<fileDesc>
<titleStmt>
<title>Texto</title>
<author>Autor desconocido</author>
<respStmt>
<resp>Codificación TEI</resp>
<name>Nombre del editor</name>
</respStmt>
</titleStmt>
<publicationStmt>
<p>Archivo creado para práctica de edición digital.</p>
</publicationStmt>
<sourceDesc>
<p>Texto preparado a partir de una transcripción de trabajo.</p>
</sourceDesc>
</fileDesc>
</teiHeader>Quédate con esta lógica:
titleStmtdice qué es y quién interviene.publicationStmtdice cómo circula el archivo.sourceDescdice de dónde sale el texto.
- Crea un
teiHeaderpropio para una obra medieval. - Añade tu nombre en un
respStmt. - Redacta un
publicationStmtbreve pero claro. - Escribe un
sourceDescfilológicamente útil y no genérico.
Lección 6: Validación y control de calidad
En esta lección aprenderás a comprobar si tu archivo XML-TEI está correcto desde dos puntos de vista:
- si está bien formado;
- si además es válido.
La meta es que no solo escribas TEI, sino que sepas detectar y corregir errores.
1. Dos niveles de corrección
Cuando trabajas con XML y TEI, hay dos preguntas distintas:
- ¿Está bien formado?
- ¿Es válido?
No significan lo mismo.
2. Qué significa “bien formado”
Un documento bien formado respeta las reglas básicas de XML.
Por ejemplo:
- tiene una sola raíz;
- cierra todas las etiquetas;
- respeta mayúsculas y minúsculas;
- anida bien los elementos;
- usa atributos correctamente.
Si falla aquí, el archivo está roto a nivel de sintaxis.
3. Qué significa “válido”
Un documento válido es un documento bien formado que además cumple las reglas de un esquema.
Ese esquema define qué elementos pueden aparecer, en qué orden, con qué atributos y en qué contextos.
En TEI, esto significa que no basta con escribir XML correcto: también debes ajustarte al modelo TEI o al esquema del proyecto.
4. Esquemas y validación
Para validar un XML se usa un esquema.
En la práctica puedes encontrar varios tipos:
- DTD
- XML Schema
- Relax NG
- Schematron
No necesitas dominar ahora sus diferencias técnicas.
Lo importante en esta fase es entender que un esquema actúa como una gramática del documento.
5. Lo que hace Oxygen
En Oxygen puedes hacer dos comprobaciones distintas:
- comprobar la buena formación del XML;
- validar el archivo contra su esquema.
Ambas son necesarias.
Un archivo puede estar bien formado y aun así no ser válido como TEI.
6. Ejemplo conceptual
Este ejemplo puede estar bien formado:
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title>Iwein</title>
</titleStmt>
<publicationStmt>
<p>Práctica</p>
</publicationStmt>
<sourceDesc>
<p>Fuente de prueba</p>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<banana>Texto</banana>
</body>
</text>
</TEI>Como XML, el documento puede estar bien cerrado.
Pero como TEI, el elemento <banana> no tiene sentido en ese contexto y el esquema lo rechazaría.
7. Estrategia de trabajo
Trabaja así:
- escribe un pequeño bloque;
- comprueba si está bien formado;
- valida contra el esquema;
- corrige el error antes de seguir;
- continúa solo cuando el documento vuelva a estar limpio.
Esto ahorra muchísimo tiempo.
8. Errores típicos que debes buscar
A. Errores de buena formación
- etiquetas sin cerrar;
- comillas ausentes en atributos;
- anidación incorrecta;
- dos raíces;
- uso incorrecto de
&o<.
B. Errores de validez TEI
- elementos no permitidos;
- elementos permitidos en lugar incorrecto;
- falta de componentes obligatorios;
- atributos no admitidos;
- orden incorrecto de subelementos.
9. Buenas prácticas
- valida a menudo;
- no acumules errores;
- corrige primero los errores estructurales;
- luego revisa los errores de esquema;
- guarda versiones del archivo conforme avanzas.
Quédate con esta fórmula:
- bien formado = sintaxis XML correcta;
- válido = sintaxis correcta + conformidad con un esquema.
Decide qué pasa en cada caso:
Caso A.
<p>Texto sin cierreCaso B.
<l n="1">Verso</l>Caso C.
<text>
<body>
<objetoInventado>Prueba</objetoInventado>
</body>
</text>- Caso A: no está bien formado.
- Caso B: puede estar bien formado.
- Caso C: puede estar bien formado como XML, pero probablemente no será válido en TEI.
- Abre uno de tus archivos TEI.
- Revisa primero si está bien formado.
- Después valídalo.
- Haz una lista de tres errores posibles: uno de sintaxis XML y dos de validez TEI.
Lección 7: Marcado filológico básico en TEI
En esta lección aprenderás a codificar algunos fenómenos filológicos fundamentales en TEI. La meta es que puedas representar no solo el texto, sino también decisiones editoriales e incertidumbres de lectura.
1. Por qué esta lección es importante
Hasta ahora has aprendido a crear la estructura general de un documento TEI.
Pero una edición filológica necesita algo más: debe poder reflejar problemas del texto.
Por ejemplo:
- abreviaturas;
- expansiones;
- errores aparentes;
- correcciones;
- formas originales y regularizadas;
- lagunas;
- lecturas dudosas;
- texto reconstruido.
Aquí es donde TEI se vuelve verdaderamente útil para edición académica.
2. El principio de choice
El elemento <choice> sirve para agrupar alternativas de codificación de una misma secuencia textual.
La idea es esta:
- una forma transmite lo que aparece en el testimonio;
- otra forma transmite la intervención editorial o la interpretación.
Por eso choice es muy útil en edición.
3. Abreviatura y expansión
Para marcar una abreviatura y su desarrollo se usan:
<abbr>para la forma abreviada;<expan>para la forma expandida.
Ejemplo:
<choice>
<abbr>dn̄</abbr>
<expan>dominus</expan>
</choice>Esto permite conservar tanto la forma abreviada del testimonio como su expansión editorial.
4. Error aparente y corrección
Para indicar que en la fuente aparece una forma aparentemente errónea, pero que el editor ofrece una corrección, se usan:
<sic>para lo transmitido;<corr>para la corrección.
Ejemplo:
<choice>
<sic>kunic</sic>
<corr>künic</corr>
</choice>La lógica es muy importante:
sic= “así está”;corr= “así lo corrijo”.
5. Forma original y forma regularizada
Si no quieres hablar de error, sino de normalización o regularización, puedes usar:
<orig>para la forma original;<reg>para la forma regularizada.
Ejemplo:
<choice>
<orig>vn̄de</orig>
<reg>unde</reg>
</choice>Esto es especialmente útil cuando no corriges un error, sino que ofreces una forma normalizada para facilitar búsqueda o lectura.
6. Lecturas dudosas
Cuando no puedes leer una palabra con total seguridad, puedes usar <unclear>.
Ejemplo:
<unclear>ritter</unclear>Eso indica que la lectura es incierta.
No quiere decir necesariamente que falte el texto, sino que su lectura no es completamente segura.
7. Lagunas
Cuando el texto falta o no puede transcribirse, se usa <gap>.
Ejemplo:
<gap reason="illegible"/>o bien:
<gap reason="lost" quantity="3" unit="words"/>Esto no reconstruye el texto: solo indica que hay una ausencia o una omisión.
8. Texto suplido
Si el editor reconstruye un pasaje perdido o ilegible, normalmente se usa <supplied>.
Ejemplo:
<supplied reason="lost">ritter</supplied>La idea es clara:
gapseñala la falta;suppliedpropone una restitución editorial.
9. Cómo decidir entre varios pares
Usa esta guía rápida:
- abreviatura desarrollada:
abbr+expan - error corregido:
sic+corr - forma original normalizada:
orig+reg - lectura insegura:
unclear - texto ausente:
gap - texto reconstruido:
supplied
10. Ejemplos integrados
Abreviatura expandida
<l n="12">er sprach ze <choice><abbr>gōt</abbr><expan>gott</expan></choice></l>Error y corrección
<l n="13">des was der <choice><sic>kunic</sic><corr>künic</corr></choice> vrô</l>Original y regularización
<l n="14">sîn <choice><orig>vn̄de</orig><reg>unde</reg></choice> sîn muot</l>Lectura dudosa
<l n="15">dô quam ein <unclear>ritter</unclear> geriten</l>Laguna
<l n="16">dô sprach <gap reason="illegible"/></l>Restitución editorial
<l n="17">dô sprach <supplied reason="lost">der ritter</supplied></l>Un error común es mezclar categorías distintas.
Por ejemplo:
- usar
corrcuando en realidad solo regularizas; - usar
regcuando en realidad corriges un error; - usar
suppliedcuando no estás reconstruyendo nada; - usar
unclearcuando en realidad el texto está ausente y deberías marcar ungap.
Quédate con esta lógica general:
- TEI permite representar el texto y la intervención editorial al mismo tiempo.
choicesirve para alternativas de codificación.sic/correxpresa corrección.orig/regexpresa regularización.abbr/expanexpresa desarrollo de abreviaturas.unclear,gapysuppliedexpresan grados distintos de incertidumbre o pérdida.
- Escribe un ejemplo con
abbryexpan. - Escribe otro con
sicycorr. - Escribe otro con
origyreg. - Añade un verso con
unclear. - Añade otro con
gap. - Añade otro con
supplied.
Código de práctica (Python)
Estas celdas son opcionales: no sustituyen a Oxygen, pero permiten manipular los mismos ejemplos como texto dentro de un cuaderno Jupyter, Colab o un chunk de Quarto/RStudio.
tei_filologico = '''<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title>Práctica filológica TEI</title>
<author>Texto medieval de ejemplo</author>
</titleStmt>
<publicationStmt>
<p>Documento de práctica para aprender marcado filológico básico.</p>
</publicationStmt>
<sourceDesc>
<p>Fragmento de prueba para abreviaturas, correcciones y lagunas.</p>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<lg type="verse">
<l n="1">er sprach ze <choice><abbr>gōt</abbr><expan>gott</expan></choice></l>
<l n="2">des was der <choice><sic>kunic</sic><corr>künic</corr></choice> vrô</l>
<l n="3">sîn <choice><orig>vn̄de</orig><reg>unde</reg></choice> muot was hôch</l>
<l n="4">dô quam ein <unclear>ritter</unclear> geriten</l>
<l n="5">dô sprach <gap reason="illegible"/></l>
<l n="6">dô sprach <supplied reason="lost">der ritter</supplied></l>
</lg>
</body>
</text>
</TEI>'''
print(tei_filologico)with open("tei_filologico_leccion7.xml", "w", encoding="utf-8") as f:
f.write(tei_filologico)
print("Archivo guardado como tei_filologico_leccion7.xml")plantilla_choice = {
"abreviatura": "<choice><abbr>dn̄</abbr><expan>dominus</expan></choice>",
"correccion": "<choice><sic>kunic</sic><corr>künic</corr></choice>",
"regularizacion": "<choice><orig>vn̄de</orig><reg>unde</reg></choice>",
"lectura_dudosa": "<unclear>ritter</unclear>",
"laguna": "<gap reason=\"illegible\"/>",
"restitucion": "<supplied reason=\"lost\">ritter</supplied>"
}
for etiqueta, ejemplo in plantilla_choice.items():
print(f"{etiqueta}: {ejemplo}")Lección 8: Aparato crítico básico en TEI
En esta lección aprenderás a representar variantes textuales básicas en TEI. La meta es que puedas codificar un aparato crítico elemental con lema, lecturas y testigos.
1. Qué es un aparato crítico en TEI
Una edición crítica no solo presenta un texto, sino también información sobre sus variantes.
TEI permite codificar esas variantes de forma estructurada.
La unidad básica del aparato crítico es <app>.
Dentro de ella suelen aparecer:
<lem>para la lectura elegida como lema o base;<rdg>para las lecturas variantes.
2. La lógica de <app>
Piensa en <app> como una cápsula que reúne todas las posibilidades de un mismo lugar textual.
Es decir:
- en un punto del texto hay una variación;
- el aparato recoge las distintas lecturas posibles;
- cada lectura puede vincularse a uno o varios testigos.
3. Elementos fundamentales
<app>
Contiene una entrada del aparato crítico.
<lem>
Contiene la lectura que el editor adopta como lema, o la lectura del testimonio base si se trabaja así.
<rdg>
Contiene una lectura variante.
4. El atributo @wit
Las lecturas se vinculan a testigos mediante @wit.
Ese atributo apunta normalmente a identificadores definidos en una lista de testigos.
Ejemplo:
<rdg wit="#A">künic</rdg>Aquí la lectura künic pertenece al testigo A.
5. Lista de testigos
Para que el aparato sea interpretable, conviene declarar los testigos en el documento.
Esto se hace con una lista como esta:
<listWit>
<witness xml:id="A">Manuscrito A</witness>
<witness xml:id="B">Manuscrito B</witness>
<witness xml:id="C">Manuscrito C</witness>
</listWit>Después, en @wit, se remite a esos identificadores:
#A#B#C
6. Ejemplo mínimo
<app>
<lem wit="#A">künic</lem>
<rdg wit="#B">kunic</rdg>
<rdg wit="#C">küning</rdg>
</app>Esto quiere decir:
- el lema adoptado es
künic, atestiguado en A; - B tiene
kunic; - C tiene
küning.
7. Inserción dentro del texto
El aparato no está aislado del texto, sino incrustado en él.
Ejemplo:
<l n="12">des was der
<app>
<lem wit="#A">künic</lem>
<rdg wit="#B">kunic</rdg>
<rdg wit="#C">küning</rdg>
</app>
vrô
</l>Así, el aparato se sitúa exactamente en el lugar del texto donde aparece la variación.
8. Qué representa el lema
Debes tener clara una cosa: <lem> no significa siempre “lectura verdadera”.
Puede representar:
- la lectura elegida por el editor;
- la lectura del testimonio base;
- la lectura que se muestra en el texto principal.
Lo importante es ser consistente y documentarlo en la edición.
9. Un ejemplo con varios testigos por lectura
Si varios testigos comparten la misma lectura, puedes agruparlos:
<app>
<lem wit="#A #B">ritter</lem>
<rdg wit="#C">reiter</rdg>
</app>Aquí A y B transmiten la misma forma.
Un error frecuente es no declarar previamente los testigos y usar @wit como si fuera una etiqueta libre.
Por ejemplo:
<rdg wit="manuscrito bueno">künic</rdg>Eso no es una buena práctica.
Es mejor definir antes los testigos con identificadores estables.
Otro error muy común es mezclar aparato crítico y corrección editorial sin distinguir niveles.
Por ejemplo:
sic/corrsirve para error y corrección editorial en un testimonio;app/lem/rdgsirve para variantes entre testigos o versiones.
No conviene usarlos como si fueran exactamente lo mismo.
Quédate con esta estructura:
<app>= unidad de variación.<lem>= lectura base o adoptada.<rdg>= lectura variante.@wit= vinculación con testigos.<listWit>= definición de los testigos.
- Crea una lista de tres testigos: A, B y C.
- Codifica una variante simple con un lema y dos lecturas.
- Inserta esa variante dentro de un verso
<l>. - Crea un segundo ejemplo en el que dos testigos compartan la misma lectura.
Código de práctica (Python)
Estas celdas son opcionales: no sustituyen a Oxygen, pero permiten manipular los mismos ejemplos como texto dentro de un cuaderno Jupyter, Colab o un chunk de Quarto/RStudio.
tei_aparato = '''<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title>Práctica de aparato crítico</title>
<author>Texto medieval de ejemplo</author>
</titleStmt>
<publicationStmt>
<p>Documento de práctica para aprender aparato crítico básico en TEI.</p>
</publicationStmt>
<sourceDesc>
<p>Fragmento didáctico con variantes entre tres testigos.</p>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<listWit>
<witness xml:id="A">Manuscrito A</witness>
<witness xml:id="B">Manuscrito B</witness>
<witness xml:id="C">Manuscrito C</witness>
</listWit>
<lg type="verse">
<l n="12">des was der
<app>
<lem wit="#A">künic</lem>
<rdg wit="#B">kunic</rdg>
<rdg wit="#C">küning</rdg>
</app>
vrô
</l>
<l n="13">dô quam ein
<app>
<lem wit="#A #B">ritter</lem>
<rdg wit="#C">reiter</rdg>
</app>
geriten
</l>
</lg>
</body>
</text>
</TEI>'''
print(tei_aparato)with open("tei_aparato_leccion8.xml", "w", encoding="utf-8") as f:
f.write(tei_aparato)
print("Archivo guardado como tei_aparato_leccion8.xml")variantes = {
"variante_1": {
"lem": "künic",
"rdg_B": "kunic",
"rdg_C": "küning"
},
"variante_2": {
"lem_AB": "ritter",
"rdg_C": "reiter"
}
}
for nombre, datos in variantes.items():
print(f"--- {nombre} ---")
for clave, valor in datos.items():
print(f"{clave}: {valor}")Lección 9: Consultar TEI con XPath
En esta lección aprenderás a hacer búsquedas estructuradas dentro de un documento XML-TEI usando XPath. La meta es que no solo codifiques textos, sino que también sepas interrogarlos.
1. Qué es XPath
XPath es un lenguaje de consulta para XML.
Sirve para seleccionar nodos dentro de un documento:
- elementos;
- atributos;
- texto;
- grupos de nodos.
Piensa en XPath como una forma de decir:
- “dame todos los versos”;
- “dame todos los párrafos”;
- “dame todos los elementos con atributo
n”; - “dame todos los
ldentro de unlg”.
2. Idea fundamental
XPath trata el XML como un árbol de nodos.
Por eso puedes recorrerlo con rutas.
Ejemplo simple:
//l
Esto significa:
“selecciona todos los elementos <l> del documento”.
3. Operadores básicos
/
Selecciona desde la raíz o marca un paso directo.
Ejemplo:
/TEI/text
//
Busca en cualquier parte del documento desde el punto actual.
Ejemplo:
//p
Esto busca todos los párrafos, estén donde estén.
@
Selecciona atributos.
Ejemplo:
//@n
Esto selecciona todos los atributos n.
.
Nodo actual.
..
Nodo padre.
4. Primeras consultas útiles
Todos los versos
//l
Todos los grupos de versos
//lg
Todos los párrafos
//p
Todas las divisiones
//div
Todos los encabezados
//head
5. Consultas con atributos
Puedes buscar elementos por atributo.
Todos los versos que tengan atributo n
//l[@n]
El verso cuyo número es 12
//l[@n='12']
Todas las divisiones de tipo poema
//div[@type='poem']
Todos los gap con razón illegible
//gap[@reason='illegible']
6. Consultas por posición
XPath permite seleccionar por posición.
El primer verso
//l[1]
El último verso
//l[last()]
El tercer párrafo
//p[3]
Recuerda: en XPath la numeración empieza en 1, no en 0.
7. Consultas jerárquicas
Puedes combinar niveles estructurales.
Todos los versos dentro de grupos de versos
//lg/l
Todos los párrafos dentro del cuerpo
//body//p
Todos los encabezados de divisiones
//div/head
Todas las lecturas variantes del aparato crítico
//app/rdg
8. Consultas muy útiles para TEI
Todas las abreviaturas
//abbr
Todas las expansiones
//expan
Todas las correcciones
//corr
Todas las formas originales
//orig
Todas las regularizaciones
//reg
Todas las lagunas
//gap
Todos los lugares con lectura dudosa
//unclear
9. Consultas con condiciones
Puedes usar filtros entre corchetes.
Todos los rdg del testigo B
//rdg[@wit='#B']
Todos los lem que pertenecen al testigo A
//lem[@wit='#A']
Todos los elementos que tienen atributo xml:id
//*[@xml:id]
Todos los elementos que tienen cualquier atributo type
//*[@type]
10. Seleccionar texto o atributos
Todos los valores del atributo n
//@n
Todos los valores del atributo wit
//@wit
El texto de todos los versos
//l/text()
Nota importante: text() devuelve nodos de texto. En documentos con marcado interno, el resultado puede fragmentarse.
11. XPath en Oxygen
Oxygen tiene una herramienta específica para ejecutar consultas XPath sobre el documento abierto.
Eso te permite:
- probar expresiones;
- comprobar si tu codificación está donde crees;
- localizar elementos problemáticos;
- revisar patrones estructurales del archivo.
XPath es útil no solo para análisis, sino también para control de calidad.
Un error típico es confundir:
/div/l
con
//div//l
No significan lo mismo.
/div/lbusca una ruta muy concreta desde la raíz.//div//lbusca cualquierldescendiente de cualquierdiven cualquier parte del documento.
13. Otra dificultad habitual
En TEI, muchas veces el documento usa namespace.
Cuando trabajas con ciertas herramientas, tendrás que declarar el namespace TEI para que XPath funcione correctamente.
En una fase inicial, lo importante es entender la lógica estructural de la consulta, aunque más adelante tendrás que aprender a manejar namespaces explícitamente.
Quédate con estas expresiones clave:
//l= todos los versos//p= todos los párrafos//div[@type='poem']= divisiones de tipo poema//l[@n='12']= verso número 12//app/rdg= variantes del aparato//*[@type]= todos los elementos con atributotype
- Busca todos los versos de tu archivo.
- Busca todos los
gap. - Busca todas las abreviaturas.
- Busca todos los elementos con atributo
n. - Busca todas las variantes del testigo B.
- Prueba una consulta para encontrar un verso concreto por número.
Código de práctica (Python)
Estas celdas son opcionales: no sustituyen a Oxygen, pero permiten manipular los mismos ejemplos como texto dentro de un cuaderno Jupyter, Colab o un chunk de Quarto/RStudio.
pip install lxmlfrom lxml import etreetei_xpath = '''<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title>Práctica XPath sobre TEI</title>
</titleStmt>
<publicationStmt>
<p>Documento didáctico.</p>
</publicationStmt>
<sourceDesc>
<p>Fuente de prueba.</p>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<div type="poem">
<head>Poema de prueba</head>
<lg type="stanza">
<l n="1">Uns ist in alten maeren</l>
<l n="2">dô quam ein <unclear>ritter</unclear></l>
<l n="3">dô sprach <gap reason="illegible"/></l>
<l n="4">
<app>
<lem wit="#A">künic</lem>
<rdg wit="#B">kunic</rdg>
</app>
</l>
</lg>
</div>
</body>
</text>
</TEI>'''
root = etree.fromstring(tei_xpath.encode("utf-8"))
ns = {"tei": "http://www.tei-c.org/ns/1.0"}
print("Documento TEI cargado.")versos = root.xpath("//tei:l", namespaces=ns)
print("Número de versos:", len(versos))
gaps = root.xpath("//tei:gap", namespaces=ns)
print("Número de gaps:", len(gaps))
lecturas_B = root.xpath("//tei:rdg[@wit='#B']", namespaces=ns)
print("Lecturas del testigo B:", [etree.tostring(x, encoding='unicode') for x in lecturas_B])
numeros_verso = root.xpath("//tei:l/@n", namespaces=ns)
print("Atributos n de los versos:", numeros_verso)Lección 10: Transformación y extracción de TEI
En esta lección aprenderás para qué sirve transformar un documento TEI y cómo empezar a hacerlo. La meta es que entiendas cómo pasar de un XML codificado a una salida útil, como HTML o texto plano.
1. Por qué transformar un TEI
Codificar en TEI no suele ser el final del proceso.
Después de codificar, normalmente quieres hacer alguna de estas cosas:
- visualizar el texto;
- publicar una versión legible;
- extraer texto plano;
- convertir el XML en HTML;
- generar otros formatos de trabajo.
Aquí entra en juego la transformación.
2. Qué es XSLT
XSLT es un lenguaje de transformación para documentos XML.
Su función es leer un XML de entrada y producir otro resultado de salida.
Ese resultado puede ser:
- otro XML;
- HTML;
- texto plano;
- otros formatos serializados.
Piensa en XSLT como un sistema de reglas que dice:
- “cuando encuentres este elemento XML, conviértelo en esta otra cosa”.
3. Idea fundamental
XSLT trabaja con plantillas.
Cada plantilla define qué hacer cuando el procesador encuentra un determinado nodo.
Por ejemplo:
- si encuentra
<title>, lo convierte en un encabezado HTML; - si encuentra
<p>, lo convierte en un párrafo HTML; - si encuentra
<l>, puede convertirlo en una línea con salto.
4. Un ejemplo mínimo: TEI a HTML
Supongamos este XML:
<text>
<body>
<p>Este es un párrafo.</p>
</body>
</text>Una transformación XSLT puede convertirlo en:
<p>Este es un párrafo.</p>5. Estructura básica de una hoja XSLT
Una hoja XSLT mínima tiene esta forma:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>Aquí:
xsl:stylesheetdeclara la hoja;xsl:template match="/"define qué hacer con la raíz;xsl:apply-templatesdice que se sigan procesando los nodos del documento.
6. Añadir reglas concretas
Puedes añadir una regla para los párrafos:
<xsl:template match="p">
<p><xsl:apply-templates/></p>
</xsl:template>Y otra para los títulos:
<xsl:template match="title">
<h1><xsl:apply-templates/></h1>
</xsl:template>La idea es simple:
- XML de entrada: describe estructura;
- XSLT: interpreta esa estructura;
- HTML de salida: la presenta visualmente.
7. Aplicado a TEI
En un documento TEI, XSLT puede usarse para transformar, por ejemplo:
<head>en<h1>o<h2>;<p>en<p>;<l>en líneas con<br/>o en bloques HTML;<lg>en un contenedor de estrofa;<choice>en distintas visualizaciones según quieras mostrar original, regularización o expansión.
Esto es importante: la transformación depende de lo que quieras mostrar.
8. Extraer texto plano
A veces no quieres HTML, sino simplemente sacar el texto del TEI.
Esto puede hacerse con XSLT o con otras herramientas.
Por ejemplo, una extracción muy simple de texto plano consiste en ignorar las etiquetas y recuperar solo el contenido textual del <body>.
Esto es útil para:
- estilometría;
- concordancias;
- análisis léxico;
- exportación a corpus de trabajo.
9. Transformación en Oxygen
Oxygen permite configurar un escenario de transformación XSLT.
La lógica general es esta:
- abrir el XML;
- abrir o crear la hoja XSLT;
- configurar el escenario de transformación;
- ejecutar la transformación;
- revisar el archivo de salida.
Es una manera muy práctica de repetir procesos sin rehacer todo cada vez.
10. Una diferencia importante
No confundas:
- consultar con XPath;
- transformar con XSLT.
XPath sirve para localizar nodos. XSLT usa XPath internamente, pero su objetivo es producir una salida nueva.
11. Ejemplo mental útil
Piensa así:
- XPath pregunta: “¿dónde están los versos?”
- XSLT dice: “cuando encuentres un verso, conviértelo en este formato de salida”.
Quédate con estas ideas:
- TEI codifica estructura y significado.
- XSLT transforma esa estructura en otra salida.
- Puedes transformar TEI a HTML, XML o texto plano.
- Oxygen permite automatizar estas transformaciones.
- XPath y XSLT están relacionados, pero no son lo mismo.
- Imagina cómo transformarías
<head>,<p>y<l>a HTML. - Piensa qué salida querrías para un
choice: original, regularizada o ambas. - Decide si para tu trabajo te interesa más transformar a HTML o extraer texto plano.
Código de práctica (Python)
Estas celdas son opcionales: no sustituyen a Oxygen, pero permiten manipular los mismos ejemplos como texto dentro de un cuaderno Jupyter, Colab o un chunk de Quarto/RStudio.
from lxml import etreetei_transformacion = '''<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>
<title>Práctica de transformación TEI</title>
</titleStmt>
<publicationStmt>
<p>Documento didáctico.</p>
</publicationStmt>
<sourceDesc>
<p>Fuente de prueba.</p>
</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>
<div type="intro">
<head>Introducción</head>
<p>Este es el primer párrafo.</p>
</div>
<div type="poem">
<head>Poema</head>
<lg type="stanza">
<l n="1">Uns ist in alten maeren</l>
<l n="2">wunders vil geseit</l>
</lg>
</div>
</body>
</text>
</TEI>'''
root = etree.fromstring(tei_transformacion.encode("utf-8"))
ns = {"tei": "http://www.tei-c.org/ns/1.0"}
print("TEI cargado.")texto_plano = " ".join(root.xpath("//tei:body//text()", namespaces=ns))
print(texto_plano)html_partes = []
for head in root.xpath("//tei:head", namespaces=ns):
html_partes.append(f"<h2>{head.text}</h2>")
for p in root.xpath("//tei:p", namespaces=ns):
html_partes.append(f"<p>{''.join(p.itertext())}</p>")
for lg in root.xpath("//tei:lg", namespaces=ns):
versos = []
for l in lg.xpath("./tei:l", namespaces=ns):
versos.append(f"<div class='verso'>{''.join(l.itertext())}</div>")
html_partes.append("<div class='estrofa'>" + "".join(versos) + "</div>")
html_salida = "<html><body>" + "".join(html_partes) + "</body></html>"
print(html_salida)Lección 11: Flujo de trabajo y publicación básica con TEI
En esta lección aprenderás a organizar un flujo de trabajo razonable para editar, validar, guardar y publicar textos TEI. La meta es que no trabajes con archivos sueltos, sino con un proceso estable y reutilizable.
1. Por qué hace falta un flujo de trabajo
En un proyecto TEI no basta con codificar bien un archivo. También necesitas saber dónde lo guardas, cómo lo validas, cómo controlas cambios y cómo produces una salida publicable.
2. Espacio de trabajo
Una práctica habitual es trabajar dentro de una carpeta de proyecto, abierta en el editor XML como espacio de trabajo. En Oxygen, ese flujo puede organizarse añadiendo una carpeta de proyecto y creando un archivo de proyecto propio.
3. Crear un archivo TEI desde plantilla
Oxygen permite crear un archivo nuevo a partir de una plantilla TEI dentro del framework correspondiente. En el flujo descrito para Oxygen, se recomienda crear el archivo desde Framework > TEI > All [TEI], lo que facilita partir de una estructura compatible desde el inicio.
4. Validar desde el principio
Cada vez que añades o modificas una parte importante del XML, conviene validar. Oxygen distingue entre comprobar la buena formación del XML y validar contra un esquema, y soporta validación con XML Schema, DTD, Schematron y Relax NG.
5. Guardar y versionar
Guardar no es suficiente si el archivo evoluciona durante semanas o meses. Por eso muchos flujos TEI combinan edición XML con Git y GitHub, de modo que cada cambio importante quede registrado en commits con mensaje descriptivo.
6. Rutina diaria recomendable
Una rutina de trabajo muy razonable es esta:
- hacer
Pullantes de empezar; - editar o crear archivos;
- validar;
- revisar cambios;
- hacer commit con un mensaje claro;
- hacer
Pushal repositorio remoto.
Esta secuencia reduce conflictos y deja trazabilidad del trabajo editorial.
7. Actualización del entorno TEI
Si trabajas regularmente con Oxygen, conviene mantener actualizado el framework TEI. El plugin TEI para Oxygen existe precisamente para mantener el entorno alineado con nuevas versiones de las Guidelines y de los estilos XSL asociados.
8. De la edición a la publicación
Una vez validado el TEI, puedes producir distintas salidas: HTML, impresión o sitios web de edición. Herramientas como TEI Publisher están pensadas para simplificar el flujo editorial y ofrecer publicación web sobre documentos TEI.
9. Publicación estática
Si no necesitas una plataforma dinámica completa, también existen enfoques de publicación estática. TEI Publisher dispone incluso de un generador estático capaz de pre-generar una versión estática de un sitio basado en TEI.
Quédate con esta cadena de trabajo:
- proyecto;
- plantilla TEI;
- edición;
- validación;
- control de versiones;
- transformación;
- publicación.
- Crea una carpeta de proyecto para tus ejercicios TEI.
- Abre esa carpeta en Oxygen.
- Crea un archivo nuevo desde plantilla TEI.
- Valídalo.
- Guarda el archivo con un nombre claro.
- Imagina qué mensaje de commit escribirías si lo subieras a GitHub.
Lección 12: TEI Publisher y MENOTA
En esta lección conocerás dos cosas complementarias:
- una herramienta para publicar ediciones TEI en la web;
- un modelo real de archivo y edición medieval digital basado en TEI.
La meta es que veas cómo tus archivos XML-TEI pueden insertarse en un ecosistema de publicación y reutilización académica.
Parte A: TEI Publisher
1. Qué es TEI Publisher
TEI Publisher es una plataforma basada en eXist-db pensada para publicar archivos TEI XML y otros tipos de XML. Se presenta como una herramienta relativamente fácil de usar para convertir XML en una aplicación o edición web publicable.
2. Para qué sirve
TEI Publisher permite publicar distintos tipos de materiales, desde presentaciones básicas de textos digitales hasta ediciones académicas más complejas. También admite distintas formas de presentación como transcripción, traducción, facsímiles y anotaciones.
3. Qué aporta a un proyecto TEI
Su valor principal es que reduce la distancia entre codificación y publicación. En lugar de limitarte a guardar XML, puedes convertir tu corpus o edición en una interfaz navegable en la web.
4. Editor de anotación
TEI Publisher incluye un editor web de anotación que ayuda a ampliar una transcripción base con anotación semántica. También existen configuraciones de anotación que pueden usarse directamente o servir como modelo para adaptaciones de proyecto.
5. Salidas y modos
TEI Publisher trabaja con varios modos de salida. Su ecosistema soporta al menos salida web y otras opciones vinculadas a impresión o generación derivada, y además existe un generador estático para pre-generar una versión estática de un sitio.
6. Por qué puede interesarte
Si tienes ya TEI bien estructurado, TEI Publisher te permite pasar de archivo codificado a edición visible sin tener que construir toda la capa web desde cero. En un curso de TEI, esto representa el puente entre edición y publicación.
Parte B: MENOTA
7. Qué es MENOTA
MENOTA significa Medieval Nordic Text Archive. Es una red de archivos, bibliotecas y departamentos de investigación que trabaja con textos medievales y facsímiles manuscritos.
8. Objetivo de MENOTA
Su objetivo es preservar y publicar textos medievales en formato digital y desarrollar los estándares de codificación necesarios para ello. El archivo incluye textos en lenguas nórdicas y también en latín.
9. Por qué importa metodológicamente
MENOTA es interesante porque muestra cómo TEI puede sostener una infraestructura completa de edición medieval digital. No es solo una colección de archivos XML, sino un modelo de archivo, publicación y reutilización académica.
10. XML descargable y reutilización
Las ediciones digitales alojadas en la plataforma tienen su XML disponible para descarga. Eso convierte a MENOTA en un recurso útil no solo para lectura, sino también para análisis, comparación y reutilización investigadora.
11. MENOTA y las extensiones TEI
MENOTA se basa en TEI, pero además define extensiones propias para problemas frecuentes en textos medievales nórdicos, especialmente la fuerte variación ortográfica y el abundante uso de abreviaturas.
12. Qué puedes aprender de MENOTA aunque no trabajes filología nórdica
Aunque tu objeto de estudio no sea nórdico, MENOTA ofrece un modelo muy valioso para pensar ediciones medievales con facsímiles, niveles de representación textual y XML reutilizable. Su interés está en la arquitectura editorial, no solo en su corpus.
Quédate con esta distinción:
- TEI Publisher = herramienta para publicar TEI;
- MENOTA = ejemplo real de archivo y edición medieval digital basada en TEI.
- Piensa si tu futuro proyecto TEI necesitaría solo archivos XML o también una publicación web.
- Imagina qué partes de tu edición se beneficiarían de una interfaz como TEI Publisher.
- Piensa qué podrías aprender de MENOTA para una edición medieval no nórdica: facsímiles, variantes, abreviaturas, niveles de texto o descarga del XML.
Consulta rápida: chuleta TEI / XML
Referencia de una página con la estructura mínima, el marcado filológico, el aparato crítico, XPath, la validación y el flujo de trabajo. Pensada para imprimirse o tenerse abierta junto a Oxygen.
- El XML primero debe estar bien formado; luego el TEI debe ser válido.
- No confundas el texto transmitido con la intervención editorial.
- Documenta siempre tus decisiones en el
teiHeader.
1. XML básico
- Una sola raíz.
- Todas las etiquetas se cierran.
- La anidación debe ser correcta.
- Los atributos van entre comillas.
- Usa entidades para caracteres reservados:
<,&.
2. Esqueleto mínimo de un documento TEI
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<teiHeader>
<fileDesc>
<titleStmt>...</titleStmt>
<publicationStmt>...</publicationStmt>
<sourceDesc>...</sourceDesc>
</fileDesc>
</teiHeader>
<text>
<body>...</body>
</text>
</TEI>fileDesces obligatorio.- Dentro:
titleStmt,publicationStmt,sourceDesc. titleStmt: título, autor, responsables.sourceDesc: de dónde sale el texto.
3. choice exprés
| Par | Significa |
|---|---|
abbr + expan |
abreviatura y su expansión |
sic + corr |
error aparente y corrección editorial |
orig + reg |
forma original y forma regularizada |
choice agrupa siempre alternativas de la misma secuencia textual.
4. Incertidumbre
unclear= lectura dudosa.gap= ausencia o ilegibilidad.supplied= restitución editorial.- No uses
suppliedsi solo estás constatando una falta: para eso estágap.
5. Aparato crítico
app= unidad de variación.lem= lectura base o adoptada.rdg= lectura variante.@witenlaza con los testigos declarados enlistWit/witness.
6. XPath exprés
| Consulta | Significa |
|---|---|
//l |
todos los versos |
//l[@n='12'] |
el verso número 12 |
//gap |
todas las lagunas |
//rdg[@wit='#B'] |
variantes del testigo B |
//*[@type] |
elementos con atributo type |
7. No confundas esto
- Bien formado = sintaxis XML correcta. Válido = además cumple el esquema.
- XPath = consulta. XSLT = transformación.
orig/reg= regularización.sic/corr= corrección editorial.
- Mezclar niveles editoriales sin explicarlos.
- Inventar valores de
@witsin una lista de testigos. - Dejar un
teiHeadervacío o demasiado pobre. - Acumular errores sin validar.
- Confundir una laguna (
gap) con una lectura dudosa (unclear). - Tratar TEI como si fuera solo formato visual.
8. Flujo de trabajo ideal
- Crear proyecto.
- Partir de plantilla TEI (en Oxygen: Framework > TEI > All [TEI]).
- Editar por bloques pequeños.
- Validar a menudo.
- Versionar con Git.
- Transformar o publicar al final (XSLT, TEI Publisher).
9. Oxygen, en una lista
- Comprueba la buena formación (well-formedness).
- Valida contra el esquema (XML Schema, DTD, Relax NG o Schematron).
- Usa XPath para revisar la estructura.
- Usa escenarios XSLT para salidas repetibles.
10. MENOTA, en una frase
Ejemplo real de archivo medieval digital basado en TEI: preservación, publicación, facsímiles, reutilización del XML y atención a problemas editoriales reales.