Introducción:
En este post aprenderás a transformar datos desde un archivo CSV a un archivo XML utilizando Java y JAXB. Este ejercicio es ideal para quienes desean trabajar con diferentes formatos de datos y conocer cómo integrar distintas técnicas en una misma aplicación.
El CSV que utilizaremos contiene información de países en el siguiente formato:
nombre,habitantes,idiomas
España,47420000,español
Francia,67750000,francés
Alemania,83200000,alemán
Italia,59110000,italiano
Suiza,8703000,alemán;francés;italiano;romanche
En el XML de salida, cada país se estructurará con atributos para el nombre y los habitantes, y tendrá un bloque <idiomas_oficiales>
en el que se listarán los idiomas oficiales. El resultado esperado para España, por ejemplo, es:
<geografía>
<paises>
<pais nombre="España" habitantes="47420000">
<idiomas_oficiales>
<idioma>español</idioma>
</idiomas_oficiales>
</pais>
...
</paises>
</geografía>
Desarrollo del Ejercicio:
En este ejercicio se realizan los siguientes pasos:
- Lectura del archivo CSV:
Se utiliza la claseBufferedReader
para leer línea a línea el archivopaises.csv
. Cada línea se divide en campos (nombre, habitantes e idiomas). En el caso de los idiomas, se admite que pueda haber más de uno, separados por el carácter;
. - Creación de objetos Java:
Se crean instancias de la clasePais
para cada línea leída, asignando sus atributos y, en caso de existir varios idiomas, se añade cada uno a una lista. - Generación del XML con JAXB:
Una vez recopilada la información, se agrupan los países en un objetoGeografia
. Con JAXB y las anotaciones correspondientes, se genera un archivo XML que cumple con la estructura deseada.
Código completo del ejercicio:
package EjerciciosClase;
import javax.xml.bind.annotation.*;
import javax.xml.bind.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class CSV_to_XML_with_JAXB {
public static void main(String[] args) {
String inputCSV = "paises.csv";
String outputXML = "paises_jaxb_from_csv.xml";
List<Pais> paises = new ArrayList<>();
// Lectura del CSV
try (BufferedReader br = new BufferedReader(new FileReader(inputCSV))) {
String line;
boolean firstLine = true;
while ((line = br.readLine()) != null) {
if (firstLine) {
// Omitir la línea de encabezado
firstLine = false;
continue;
}
// Se espera el formato: nombre,habitantes,idiomas
String[] parts = line.split(",");
if (parts.length < 3) continue;
Pais pais = new Pais();
pais.setNombre(parts[0].trim());
pais.setHabitantes(parts[1].trim());
// Los idiomas pueden estar separados por ";"
String idiomasStr = parts[2].trim();
String[] idiomasArray = idiomasStr.split(";");
for (String idioma : idiomasArray) {
pais.addIdioma(idioma.trim());
}
paises.add(pais);
}
} catch (IOException e) {
e.printStackTrace();
}
// Creación del objeto Geografia con la lista de países
Geografia geografia = new Geografia();
geografia.setPaises(paises);
// Generación del XML usando JAXB
try {
JAXBContext jaxbContext = JAXBContext.newInstance(Geografia.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(geografia, new File(outputXML));
System.out.println("Archivo XML generado: " + outputXML);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
@XmlRootElement(name = "geografía")
@XmlAccessorType(XmlAccessType.FIELD)
class Geografia {
@XmlElementWrapper(name = "paises")
@XmlElement(name = "pais")
private List<Pais> paises;
public List<Pais> getPaises() { return paises; }
public void setPaises(List<Pais> paises) { this.paises = paises; }
}
@XmlAccessorType(XmlAccessType.FIELD)
class Pais {
@XmlAttribute(name = "nombre")
private String nombre;
@XmlAttribute(name = "habitantes")
private String habitantes;
@XmlElementWrapper(name = "idiomas_oficiales")
@XmlElement(name = "idioma")
private List<String> idiomas = new ArrayList<>();
public String getNombre() { return nombre; }
public void setNombre(String nombre) { this.nombre = nombre; }
public String getHabitantes() { return habitantes; }
public void setHabitantes(String habitantes) { this.habitantes = habitantes; }
public List<String> getIdiomas() { return idiomas; }
public void setIdiomas(List<String> idiomas) { this.idiomas = idiomas; }
public void addIdioma(String idioma) {
this.idiomas.add(idioma);
}
}
Explicación del Código:
- Lectura del CSV:
Se utilizaBufferedReader
para leer el archivo línea por línea. La primera línea se omite, ya que contiene los encabezados. Cada línea se separa en partes usando la coma como delimitador. Para el campo de idiomas, se hace una división adicional por el carácter;
para soportar múltiples idiomas. - Conversión a objetos Java:
Por cada línea se crea un objeto de tipoPais
, asignándole el nombre, el número de habitantes y una lista de idiomas. Estos objetos se almacenan en una lista. - Generación del XML con JAXB:
Se crea un objetoGeografia
que actúa como contenedor raíz y contiene la lista de países. Mediante las anotaciones JAXB (@XmlRootElement
,@XmlAccessorType
,@XmlElementWrapper
y@XmlElement
), se genera un XML formateado con la estructura deseada.
Conclusión:
Este ejercicio demuestra cómo integrar la lectura de un archivo CSV y la generación de un XML utilizando JAXB en Java. Es una excelente práctica para quienes desean trabajar con diferentes formatos de datos y combinarlos en aplicaciones Java. ¡Prueba este ejercicio en tus proyectos y comparte tus experiencias en los comentarios!
