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?