Lectura de ficheros XML con Java

En esta entrada vamos a tratar lo que supondría la primera toma de contacto para alguien que está empezando a programar con el almacenamiento de la información en ficheros XML. Vamos a centrarnos en la lectura de un fichero, del cual conocemos su contenido, sin esquema xsd, y obtendremos la información almacenada que guardaremos en objetos. En futuras entradas se tratará como añadir información al fichero xml o cómo editarla.

Supongamos que tenemos este fichero que nos muestra la estructura de un departamento de alguna empresa. En él tenemos un director, con su nombre, antigüedad y salario, y varios trabajadores, con su nombre, antigüedad, salario y un código de nivel.

<?xml version="1.0" encoding="UTF-8"?><departamento>
 <director>
  <nombre>Isabel Sanz</nombre>     
  <antiguedad>9</antiguedad>     
  <salario>2500</salario>
 </director>
 <trabajadores>
  <trabajador nivel="A5">
   <nombre>Javier Salazar</nombre>
   <antiguedad>3</antiguedad>
   <salario>1650</salario>
  </trabajador>
  <trabajador nivel="B2">
   <nombre>Raquel Ramirez</nombre>
   <antiguedad>5</antiguedad>  
   <salario>1800</salario>
  </trabajador>
 </trabajadores>
</departamento>

Para almacenar la información en objetos, en primer lugar, habrá que definir esas clases. Así pues, tendremos la clase director:

public class Director {
 private String nombre;
 private int antiguedad;
 private int salario;

 public void setNombre(String nombre){
  this.nombre = nombre;
 }
 public String getNombre(){
  return nombre;
 }                
 public void setAntiguedad(int antiguedad)  
 {                    
  this.antiguedad = antiguedad;
 }             
 public int getAntiguedad(){
  return antiguedad;
 }            
 public void setSalario(int salario){
  this.salario = salario;
 }            
 public int getSalario(){
  return salario;
 }
}

La clase trabajador:

public class Trabajador {
 private String nombre;
 private int antiguedad;
 private int salario;
 private String nivel;

 public void setNombre(String nombre){
  this.nombre = nombre;
 }
 public String getNombre(){
  return nombre;
 }                
 public void setAntiguedad(int antiguedad)  
 {                    
  this.antiguedad = antiguedad;
 }             
 public int getAntiguedad(){
  return antiguedad;
 }            
 public void setSalario(int salario){
  this.salario = salario;
 }            
 public int getSalario(){
  return salario;
 }
 public void setNivel(String nivel){
  this.nivel = nivel;
 }
 public String getNivel(){
  return nivel;
 }
}

Y, por último, la clase departamento, que contendrá un objeto Director y una lista de objetos Trabajador:

public class Departamento {
 private Director director;
 private ArrayList<Trabajador> trabajadores;

 public Departamento(){
  trabajadores = new ArrayList();
 }

 public Director getDirector(){
  return director;
 }                
 public void setDirector (Director director)  {                    
  this.director = director;
 }             
 public int getAntiguedad(){
  return antiguedad;
 }            
 public void setTrabajadores(ArrayList<Trabajador> trabajadores){
  this.trabajadores = trabajadores;
 }            
 public ArrayList<Trabajador> getTrabajadores() {
  return trabajadores;
 }
}

Para poder leer la información del xml hay que construir un objeto de tipo Documento que contendrá el modelo de objetos del documento, el DOM. Se trata de una interfaz que permite guardar objetos para representar documentos xml y html.

La conversión entre el xml y el DOM se realiza con las clases DocumentBuilderFactory y DocumentBuilder del paquete javax.xml.parsers, del cual podéis obtener más información aquí.

En resumen, se debe crear un objeto de tipo DocumentBuilder, que se crea a través de un objeto de tipo DocumentBuilderFactory. Para construir el DOM utilizamos el método parse del objeto DocumentBuilder pasándole como parámetro la ruta del archivo XML y almacenando el resultado en un objeto de tipo Document.

El siguiente método leería un xml, cuya ruta se ha introducido como parámetro, y devolvería un objeto de tipo Document que contendría el DOM.

public static Document LeerXML(String RutaArchivoXML){
//Declaramos la variable dom, que almacenará el DOM,
// y la inicializamos en null. 
 Document dom = null;
  try{
//Instanciamos el creador de construtores de documento 
  DocumentBuilderFactory dbf =   
   DocumentBuilderFactory.newInstance();
  DocumentBuilder db = 
   dbf.newDocumentBuilder();
//Leemos el documento y lo convertimos en DOM guardándolo
//en la variable dom 
  dom = db.parse(RutaArchivoXML);
 } catch (Exception ex) {
Logger.getLogger(AD_Tarea02.class.getName()).log(Level.SEVERE, "Error en la lectura del fichero XML", ex);
}
return dom;
}

Una vez almacenados los datos en el DOM debemos acceder a ellos para guardarlos en los objetos que hemos definido. Para realizar esto hay que utilizar los métodos get que tiene el dom e ir buscando los elementos y sus atributos por el nombre de las etiquetas. Así pues, es necesario que conozcamos la estructura del documento xml.

En primer lugar, crearemos listas de nodos buscando todos los nodos que contengan una determinada etiqueta. Tras esto, para acceder a la información dentro de esas etiquetas, tenemos que crear un elemento para cada uno de los registros guardados en la lista de nodos.

En el ejemplo en el que nos encontramos sabemos que solo hay un elemento de tipo “director”, por lo que podremos crear el elemento directamente desde la posición 0 de la lista de nodos. En el caso de los trabajadores, sin embargo, al haber más de uno, habrá que ir recorriendo la lista de nodos correspondiente para ir leyendo los distintos trabajadores uno a uno.

El siguiente método lee los datos almacenados en el DOM y crea los objetos director, alumnos y departamento con los datos del DOM. Devuelve un objeto de tipo Departamento que contendrá los datos del profesor y de todos los alumnos.

public static Departamento LeerDatos(Document dom){
//Inicializamos los objetos donde almacenaremos los datos //leídos del DOM.  
  Director director = new Director();
  Departamento departamento = new departamento();
//Leemos los nodos que contiene la etiqueta director 
  NodeList nodosDirector = dom.getElementsByTagName("director");
//Declaramos un objeto Element que almacene la información 
//de ese nodo, ya que en este caso sabemos que solo hay 
//uno.  
  Element elementDir =(Element) nodosDirector.item(0);
//Almacenamos los datos en el objeto director buscando por 
//etiquetas que sabemos que son únicas dentro de cada 
//elemento director.
  
director.setNombre(elementDir.getElementsByTagName("nombre").item(0).getTextContent());
//Los datos obtenidos son de tipo String, por lo que habrá 
//que transformarlos al tipo necesario.
  
director.setAntiguedad(Integer.parseInt(elementDir.getElementsByTagName("antiguedad").item(0).getTextContent()));
  
director.setSalario(Integer.parseInt(elementDir.getElementsByTagName("salario").item(0).getTextContent()));
//Guardamos el objeto director en el objeto departamento. 
  departamento.setDirector(director);
//Leemos los nodos que contiene la etiqueta trabajador 
  NodeList nodosTrabajador = dom.getElementsByTagName("trabajador");
//Es posible que exista más de un elemento trabajador, por 
//lo que tenemos que recorrer con un for los nodos para ir 
//guardando los datos en el objeto trabajador e ir 
//añadiéndolos al ArrayList de trabajadores. 
  for (int i = 0; i < nodosTrabajador.getLength(); i++){  
    if (nodosTrabajador.item(i).getNodeType() == Node.ELEMENT_NODE){
      Trabajador trabajador = new Trabajador();
      Element elementTrabajador = (Element) nodosTrabajador.item(i);
                trabajador.setNombre(elementTrabajador.getElementsByTagName("nombre").item(0).getTextContent());
                trabajador.setAntiguedad(Integer.parseInt(elementTrabajador.getElementsByTagName("antiguedad").item(0).getTextContent()));
                trabajador.setSalario(Integer.parseInt(elementTrabajador.getElementsByTagName("salario").item(0).getTextContent()));
//Los atributos se leen con el método getAttribute. 
             trabajador.setNivel(elementTrabajador.getAttribute("nivel").item(0));
//Añadimos el trabajador al arrayList 
      departamento.getTrabajadores().add(trabajador);
      }        
    }        
  return departamento;
}

En futuras entradas incluiremos métodos que permitan añadir información al DOM, guardarla en el archivo xml de forma persistente y editar la información de alguna etiqueta.

Deja un comentario