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 Pe...

Soluciones Alchemy Classic 442 elementos

Después de la resaca navideña y de la cuesta de enero, volvemos para informar la agradable sorpresa que nos ha dado a los fans de Alchemy Classic la empresa NIASOF ,  tras actualizar el juego Alchemy Classic. Una nueva versión con 442 elementos , interfaz mejorada de grupos y lo más importante, nuevos elementos que descubrir. La gran novedad de esta actualización son los puntos que tienes asignados , con los que puedes  conseguir pistas sobre los elementos que no has abierto todavía como: Conseguir un subelemento de un elemento, con 100 puntos . Conseguir el grupo de un subelemento de un elemento (qué lío , jeje), con 35 puntos . Me gusta, me gusta el enfoque de esta nueva versión aunque los elementos que han sacado me parecen poco originales. Parece que se van agotando las ideas para los elementos nuevos. Aquí van las soluciones: Carbon = Tierra + Turba Sol = Estrella + Tierra Espacio = 3 x Estrella Estrella = Helio + Hidrógeno Oso Pa...

Alchemy Classic

Dentro de los juegos que he descargado con el Android Market hay dos que destacan sobre todos los demás. El primero es Angry Birds (pájaros furiosos), en el cual comandas un ejercito de pájaros para luchar con una piara de cerdos malotes los cuales han robado sus huevos. Básicamente, tienes que ir pasando nivel tras nivel afinando tu puntería lanzando los pájaros a los cerdos que se esconden tras maderas, cristales y piedras. Pero la verdadera joya que no es tan conocida es Alchemy Classic . En este juego puedes desempeñar el papel  de Dios. Comenzando con 4 elementos básicos, Aire, Agua, Tierra y Fuego tienes que ir obteniendo todos los demás elementos de la creación (animales, plantas, herramientas...) mediante la combinación de los 4 primeros. En total hay 238 elementos. Después de una semana y alguna noche sin dormir por fin los he obtenido todos. El último elemento me ha llevado más de la cuenta por su maravillosa traducción. ¿Qué son abrojos? ¿Lo sabéis? Pues no, ...