Ejercicio: Analizador SAX de Catálogo de Videojuegos
Contexto
Dispones de un archivo XML grande con el catálogo de videojuegos de una tienda online. Debes implementar un analizador en streaming con SAX que genere estadísticas y exporte un resumen en CSV sin cargar el XML completo en memoria.
Objetivos de aprendizaje
- Usar
SAXParsery unDefaultHandler. - Gestionar
startElement,characters(fragmentación de texto) yendElement. - Leer atributos, namespaces y CDATA como texto.
- Implementar estado interno y acumuladores de forma eficiente.
- Endurecer el parser contra XXE con features de seguridad.
- (Opcional) Validar con XSD.
Datos de entrada
Archivo: catalogo_juegos.xml (ejemplo reducido)
<?xml version="1.0" encoding="UTF-8"?>
<cat:catalogo xmlns:cat="http://ejemplo.com/juegos" xmlns:met="http://ejemplo.com/meta" generado="2025-10-01">
<cat:juego id="J001" plataforma="PC">
<cat:titulo><![CDATA[Hollow Knight]]></cat:titulo>
<cat:genero>Metroidvania</cat:genero>
<cat:precio moneda="EUR">14.99</cat:precio>
<met:rating>4.7</met:rating>
<cat:fecha>2017-02-24</cat:fecha>
<cat:tags><cat:tag>indie</cat:tag><cat:tag>2D</cat:tag></cat:tags>
</cat:juego>
<cat:juego id="J002" plataforma="Switch">
<cat:titulo>The Legend of Zelda</cat:titulo>
<cat:genero>Aventura</cat:genero>
<cat:precio moneda="EUR">59.99</cat:precio>
<met:rating>4.9</met:rating>
<cat:fecha>2023-05-12</cat:fecha>
<cat:tags><cat:tag>exclusivo</cat:tag></cat:tags>
</cat:juego>
<cat:juego id="J003" plataforma="PC">
<cat:titulo>Factorio</cat:titulo>
<cat:genero>Gestión</cat:genero>
<cat:precio moneda="USD">35.00</cat:precio>
<met:rating>4.8</met:rating>
<cat:fecha>2020-08-14</cat:fecha>
<cat:tags><cat:tag>automation</cat:tag><cat:tag>mods</cat:tag></cat:tags>
</cat:juego>
</cat:catalogo>
(Se asumirá un archivo real con miles de <cat:juego>.)
Requisitos funcionales
- Entrada por CLI
El programa se invoca así:java -jar sax-juegos.jar --in catalogo_juegos.xml --out resumen.csv \ --min-rating 4.5 --plataforma PC --genero Metroidvania--in: ruta al XML (obligatorio)--out: ruta al CSV de salida (obligatorio)- Filtros opcionales:
--min-rating <double>,--plataforma <string>,--genero <string> - Si no hay filtros, procesa todo.
- Procesamiento en streaming (SAX)
- Prohibido usar DOM u otras librerías que construyan árbol completo.
- Gestiona correctamente que
characters()puede ser invocado varias veces por el mismo texto.
- Extracción de campos por juego
Para cada<cat:juego>debes extraer:id(atributo)plataforma(atributo)titulo,genero,precio(texto),moneda(atributo de<cat:precio>),rating(<met:rating>),fechatags(concatenados por;)
- Salida CSV
Escribe un CSV con cabecera:id;plataforma;titulo;genero;precio;moneda;rating;fecha;tagsSolo incluir filas que cumplan los filtros. - Estadísticas en consola (al finalizar)
- Total de juegos leídos.
- Total de juegos emitidos tras filtros.
- Conteo por plataforma (PC, Switch, PlayStation, etc.).
- Precio medio por género (solo moneda EUR; ignora otras monedas para la media).
- Top 3 por
rating(muestraid,titulo,rating).
- Namespaces
- Activa
namespaceAware. - Funciona correctamente con prefijos
cat:ymet:(no asumasqName).
- Activa
- Seguridad
- Deshabilita DOCTYPE y entidades externas (XXE).
- No aceptes XInclude.
- Gestión de errores
- Implementa un
ErrorHandlerque muestre línea/columna. - Ignora de forma segura juegos con datos obligatorios faltantes (loggea y continúa).
- Implementa un
Requisitos no funcionales
- Eficiencia: O(1) memoria respecto al tamaño del archivo (solo buffers necesarios).
- Código limpio:
Handlerseparado de la claseMain. - Mensajes de log claros.
- Tests unitarios para, al menos, la normalización de texto y el parseo de atributos.
Entregables
README.mdcon instrucciones de compilación/ejecución.src/main/java/...Main.java(parsea args y lanza el parser)JuegosHandler.java(extiendeDefaultHandler)ModeloJuego.java(POJO simple)AppErrorHandler.java(errores SAX)CsvWriter.java(emisión de filas)
data/catalogo_juegos.xml(mínimo 20 juegos de prueba).out/resumen.csv(generado).- (Opcional)
schema/catalogo_juegos.xsd.
Criterios de evaluación (rúbrica)
- Correctitud SAX (30
- Filtros y salida (25
- Estadísticas (20
- Seguridad y robustez (15
- Calidad del código (10
Retos opcionales (+bonus)
- Parada temprana: añade
--top-n 100y detén el parseo cuando hayas emitido N juegos que cumplan filtros (lanza y captura unaSAXExceptionpropia). - Conversión de moneda: añade
--eur-onlyy descarta juegos no EUR; o (más difícil) convierte USD→EUR con una tasa fija--usd-rate 0.92. - Validación XSD: valida el XML contra
catalogo_juegos.xsde informa errores de esquema. - Resumen JSON: además del CSV, crea
resumen.jsoncon las estadísticas finales. - Rutas: imprime la ruta XPath-like del elemento cuando falte un campo obligatorio.
¿Quieres que te dé el esqueleto de clases (sin implementar la lógica) o un XML más largo para pruebas?