Ir al contenido principal

JAXB: Leer y escribir ficheros XML

Muchas veces en nuestras aplicaciones debemos manejar documentos XML (Extensible Markup Language). Este lenguaje se ha convertido en un estándar para intercambio de datos entre programas y aplicaciones a través de Internet. En un esquema XML (o XSD) podemos definir los elementos que pueden aparecer en un documento XML así como las relaciones entre los mismos.

JAXB (Java Architecture for XML Binding) es un estándar Java para transformar un esquema XML (o XSD) en una representación a objetos java. Mediante la API de JAXB podemos mapear un objeto Java a un documento XML ("marshall") y el proceso contrario, es decir, a partir de un esquema XML crear su conjunto de objeto Java asociado ("unmarshall").


JAXB

Resumiendo lo que nos proporciona JAXB es:
  • Generación de objetos Java a partir de un XSD a través de un compilador
  • Proporciona capacidades de marshall/unmarshall (escribir fichero XML desde java y al contrario)
  • Integración con Maven a través de xjc (desde Java 1.6)
  • Validación de nuestro documento XML a partir de un XSD

Existen otras herramientas para manejar XML desde Java como por ejemplo  Xstream.  Mi amigo y compañero el señor Fuente lo explica perfectamente en un tutorial. Depende de los requisitos de nuestro proyecto deberíamos utilizar una u otra herramienta, puesto que cada una tiene sus ventajas e inconvenientes. Con Xstream no se pueden generar clases Java a partir de un esquema de datos dado y con JAXB sí. Sin embargo, Xstream es más sencillo de utilizar y las clases del modelo que se mapean a/desde XML no necesitan añadir etiquetas adicionales (pueden ser simples beans).


A continuación os voy a poner unos ejemplos con JAXB. Los ejemplos los he realizado con Eclipse 3.6 (Helios) y Java 1.6. En esta versión se incluyen las capacidades de JAXB (es una ventaja no añadir ninguna librería adicional).

El ejemplo consiste en crear dos entidades Java, Empresa y Empleado. Una Empresa está compuesta por un conjunto de Empleados. Las anotaciones que se utilizan en estas dos clases son las siguientes:


  • @XmlRootElement(name = "empleado").  Define que el elemento raíz del objeto Java se llamará empleado.
  • @XmlType(propOrder = { "dni", "nombre", "edad", "puesto" }). Define el orden de los elementos dentro de otro elemento. 
  • @XmlElement(name = "cargo"). Sirve para cambiar el nombre de un elemento en el documento XML. Por defecto el elemento aparece con el nombre del atributo de la clase Java pero podemos cambiarlo con esta etiqueta. En el ejemplo se cambia el nombre puesto por cargo. Se puede utilizar en los atributos tipo lista para indicar cómo se llamará cada elemento de la lista. 
  • @XmlElementWrapper(name = "empleados"). Para crear un wrapper llamado empleados que englobe la estructura XML de los objetos Empleado.

A continuación tenéis el código de la clase Empresa:



package es.jpascu.jaxb;

import java.util.ArrayList;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "empresa")
public class Empresa {
 private String cif;
 private String nombre;
 private ArrayList empleados;

 public String getCif() {
  return cif;
 }

 public void setCif(String cif) {
  this.cif = cif;
 }

 public String getNombre() {
  return nombre;
 }

 public void setNombre(String nombre) {
  this.nombre = nombre;
 }

 @XmlElementWrapper(name = "empleados")
 @XmlElement(name = "empleado")
 public ArrayList getEmpleados() {
  return empleados;
 }

 public void setEmpleados(ArrayList empleados) {
  this.empleados = empleados;
 }

}


Y el código de la clase Empleado:


package es.jpascu.jaxb;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlRootElement(name = "empleado")
@XmlType(propOrder = { "dni", "nombre", "edad", "puesto" })
public class Empleado {
 private String dni;
 private String nombre;
 private int edad;
 private String puesto;
 public String getDni() {
  return dni;
 }
 public void setDni(String dni) {
  this.dni = dni;
 }
 public String getNombre() {
  return nombre;
 }
 public void setNombre(String nombre) {
  this.nombre = nombre;
 }
 public int getEdad() {
  return edad;
 }
 public void setEdad(int edad) {
  this.edad = edad;
 }
 @XmlElement(name = "cargo")
 public String getPuesto() {
  return puesto;
 }
 public void setPuesto(String puesto) {
  this.puesto = puesto;
 }
 
 
}

Por último, ponemos el código de una clase de prueba que hace uso de la API de JAXB para rellenar el modelo de objetos Java  (empresa y empleados) y crear un XML a partir del mismo. Posteriormente, con el XML guardado en disco, se realiza el proceso contrario, cargar la información del XML en el objeto Empresa. El código lo tenéis  aquí:



package es.jpascu.jaxb;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class JaxbTest {
 private final static String XML_EMPLEADOS = "./info-empleados.xml";

 public static void main(String[] args) throws JAXBException, IOException {

  // Primero rellenamos los objetos Java y generamos un XML

  ArrayList empleados = new ArrayList();

  Empleado empleado1 = new Empleado();
  empleado1.setDni("12345678C");
  empleado1.setNombre("Carlos Pérez Ruíz");
  empleado1.setEdad(29);

  Empleado empleado2 = new Empleado();
  empleado2.setDni("87654321C");
  empleado2.setNombre("Claudia Ortiz Zaldo");
  empleado2.setEdad(31);

  Empresa empresa = new Empresa();
  empresa.setCif("A58818501");
  empresa.setNombre("TECNOMUR S.L.");
  empleados.add(empleado1);
  empleados.add(empleado2);
  empresa.setEmpleados(empleados);

  // Creamos el contexto e instanciamos el marshaller
  JAXBContext context = JAXBContext.newInstance(Empresa.class);
  Marshaller m = context.createMarshaller();
  m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
  m.marshal(empresa, System.out);

  Writer w = null;
  try {
   w = new FileWriter(XML_EMPLEADOS);
   m.marshal(empresa, w);
  } finally {
   try {
    w.close();
   } catch (Exception e) {
   }
  }

  // Ahora leemos el XML e instanciamos las clases Java
  System.out.println("Salida desde el fichero XML: ");
  Unmarshaller um = context.createUnmarshaller();
  Empresa empresa2 = (Empresa) um
    .unmarshal(new FileReader(XML_EMPLEADOS));

  for (int i = 0; i < empresa2.getEmpleados().toArray().length; i++) {
   System.out.println("Empleado " + (i + 1) + ": "
     + empresa2.getEmpleados().get(i).getNombre() + " con DNI "
     + empresa2.getEmpleados().get(i).getDni() + " y "
     + empresa2.getEmpleados().get(i).getEdad() + " años");
  }

 }
}



Referencias: Oracle | Vogella

Comentarios

  1. a mi me gustaria ver como esta escrito tu .xml

    ResponderEliminar
  2. a mi me gustaria ver como esta escrito tu .xml

    ResponderEliminar
  3. Muchas gracias! muy buen aporte y bien explicado

    ResponderEliminar
  4. Buen día, estoy tratando de usar su ejemplo aplicándolo a mi propio entorno y necesidad, usando una clase generada por el JAXB, pero la referencia que usted usa al final no la puedo usar ya que mi clase tiene otro nombre y no se que poner ahí, tengo un error de compilación, mucho agradeceré su ayuda

    ResponderEliminar
  5. asi estaría bien? Gracias desde Santiago

    private void leerXML(Node nodo) {
    NodeList hijos = nodo.getChildNodes();

    for (int i = 0; i < hijos.getLength(); i++) {
    Node hijo = hijos.item(i);
    String s = hijo.getParentNode().getNodeName();
    if (hijo.hasChildNodes()) {
    leerXML(hijo);
    } else {

    if (s.equals("primerElemento")) {
    System.out.print(hijo.getNodeValue() );
    } else if (s.equals("segundoElemento")) {
    System.out.print(hijo.getNodeValue()");
    } else if (s.equals("tercerElemento")) {
    System.out.println(hijo.getNodeValue());
    }
    }
    }
    }

    public void imprimirXML() {
    File xmlFile = new File ("xml");
    try{
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(xmlFile);
    Node raiz = doc.getFirstChild();

    leerXML(raiz);
    }catch (Exception e){
    e.printStackTrace();
    }
    }

    ResponderEliminar

Publicar un comentario

Entradas populares de este blog

Soluciones Alchemy Classic 389 elementos

Hace algún tiempo salió una actualización del Juego Alchemy Classic en la que aparecían más elementos (389 en lugar de 238). Aparte de añadir elementos mejoran algunas traducciones en castellano y mejoran la interfaz, aunque todavía hay algún error en algunos nombres de elementos. Aquí os dejo las soluciones para los que estén atascados y no puedan dormir por las noches: Sustancia primaria Aire=Elemento primario  Fuego=Elemento primario  Agua=Elemento primario  Tierra=Sustancia Primaria Arena=Piedra + Aire Piedra=Tierra + Fuego Arcilla=Arena + Pantano Caliza=Tierra + Amonitas Carbono=Fuego + Madera Cloro=Fuego + Sal + Electricidad CO2(Dióxido de Carbono)=Ceniza + Ácido nítrico Electricidad=Relámpago+ Metales Gas natural= Yacimiento de gas + Pozo Helio=Refinería de gas + Gas Natural Hidrógeno=Electricidad + Agua Hielo=Frío + Agua Imán=Piedra + Metales Metano=Deshechos Vegetales + Pantano Oxígeno=Electricidad + Agua Petróleo=Unidad

Matemáticas y cine.

El otro día estaba viendo por la televisión una película llamada 21 blackjack . En una escena de la película el profesor de matemáticas ( Kevin Spacey ) le presenta a uno de sus alumnos la siguiente situación: se encuentra en un concurso en la que debe escoger entre tres puertas (1,2 y 3). En dos de ellas hay una cabra, sin embargo en una de las 3 hay un flamante coche nuevo. El alumno responde que quiere abrir la puerta. El presentador, conocedor de lo que hay detrás de cada puerta decide abrir otra puerta diferente mostrando detrás de ella una cabra. El profesor se dirige al alumno y le pregunta, ¿cambiarías la puerta o te quedarías con la puerta que tienes? Muchos de nosotros cambiaríamos de puerta pensando que es una treta del presentador para engañarnos. ¿Cual elegiríais vosotros? Al comienzo tenemos 1/3 de probabilidades de acertar la puerta donde está el coche. Una vez que el presentador abre la puerta con una cabra, la mayoría de gente piensa que hay la misma probabilidad de