| Manipular un Documento XML con JAXB a partir de un XML Schema |
| Paso 3: Operativa |
Creación de un documento XML 
En la carpeta C:\isg\j2se\prosjava\projaxb nos creamos un documento XML llamado pedido.xml. Este es el contenido de este fichero
<?xml version="1.0" encoding="UTF-8"?>
<pedido xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation='pedido.xsd'>
<enviarA pais="EEUU">
<nombre>Alice Smith</nombre>
<calle>123 Maple Street</calle>
<ciudad>Cambridge</ciudad>
<estado>MA</estado>
<codigoPostal>12345</codigoPostal>
</enviarA>
<facturarA>
<nombre>John Bob</nombre>
<calle>242 Main Street</calle>
<ciudad>Beverly Hills</ciudad>
<estado>CA</estado>
<codigoPostal>90210</codigoPostal>
</facturarA>
<comentario>Líneas de pedido</comentario>
<articulos>
<articulo codigoStock="872-AA">
<nombreProducto>Cortacésped</nombreProducto>
<cantidad>1</cantidad>
<precioEEUU>148.95</precioEEUU>
<comentario>Eléctrico con baterías recargables</comentario>
<fechaEnvio>2006-06-28</fechaEnvio>
</articulo>
<articulo codigoStock="926-BC">
<nombreProducto>Bolsa de tierra de abono marca Acme</nombreProducto>
<cantidad>1</cantidad>
<precioEEUU>7.20</precioEEUU>
</articulo>
</articulos>
</pedido> |
Crear una Clase que modifica de forma transparente un documento XML
Este es el código fuente correspondiente a la Clase ModificaMuestraPedido que pertenece al paquete paqjaxb
package paqjaxb;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import jaxb.pedido.DireccionEEUU;
import jaxb.pedido.PedidoType;
public class ModificaMuestraPedido {
public static void main(String[] args) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance("jaxb.pedido");
Unmarshaller u = jaxbContext.createUnmarshaller();
JAXBElement jaxbElement = (JAXBElement) u.unmarshal(
new FileInputStream("pedido.xml"));
PedidoType pedidoType = (PedidoType) jaxbElement.getValue();
DireccionEEUU direccionEEUU = pedidoType.getFacturarA();
direccionEEUU.setNombre("Julian Nader");
direccionEEUU.setCalle("25 Lake Street");
direccionEEUU.setCiudad("Mission Viejo");
direccionEEUU.setEstado("CA");
direccionEEUU.setCodigoPostal(new BigDecimal("92692"));
Marshaller m = jaxbContext.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(jaxbElement, System.out);
} catch (JAXBException je) {
je.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
|
- JAXBContext jaxbContext = JAXBContext.newInstance("jaxb.pedido");
- creamos una instancia de la Clase JAXBContext para así de esta forma poder manipular las Clases generadas en el paquete jaxb.pedido
- la Clase JAXBContext provee al cliente un punto de entrada a la API JAXB
- de hecho nos facilita una abstracción para manejar la información generada para implementar las operaciones del JAXB binding framework como unmarshal y marshal
- unmarshal
- consiste en convertir
- datos XML en un árbol de objetos Java que representan dichos datos
- marshal
- cosnsiste en convertir
- un árbol de objetos Java a datos XML
- Unmarshaller u = jaxbContext.createUnmarshaller();
- creamos un objeto de tipo Unmarshaller para posteriormente convertir datos XML en un árbol de objetos Java
- JAXBElement jaxbElement = (JAXBElement) u.unmarshal(
new FileInputStream("pedido.xml"));
- la Clase JAXBElement representa a un elemento de un documento XML
- en nuestro caso representa al elemento raíz del documento pedido.xml
- PedidoType pedidoType = (PedidoType) jaxbElement.getValue();
- el método getValue() retorna el modelo de contenido (content model) y el valor de los atributos del elemento
- DireccionEEUU direccionEEUU = pedidoType.getFacturarA();
- hablamos con una instancia de tipo PedidoType para obtener un Objeto de tipo DireccionEEUU
- direccionEEUU.setNombre("Julien Naider");
- ahora ya estamos hablando con el objeto de tipo DireccionEEUU para modificar la dirección de facturación
- Marshaller m = jaxbContext.createMarshaller();
- creamos un objeto de tipo Marshaller para posteriormente convertir un árbol de objetos Java a datos XML
- m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
- el método setProperty(String nombrePropiedad, Object value) recibe en este caso la propiedad "jaxb.formatted.output"
- esta propiedad controla si al realizar un marshal formateará el resultado XML con saltos de linea e indentaciones para que las personas podamos leerlo cómodamente
- por defecto su valor es falso
- es decir el XML creado no está formateado
- el argumento value en este caso tiene que ser concretamente de tipo Boolean
- para indicar si queremos que el resultado XML esté formateado o no
- m.marshal(jaxbElement, System.out);
- el método marshall(Object elementoJAXB, OutputStream os) recibe un objeto de tipo JAXBElement para que su contenido lo muestre en la salida estándar
- debido a que este método está sobrecargo, si miramos la documentación de la API podemos ver como podemos mostrar o escribir el resultado XML de diferentes maneras
Realizamos un Clean and build del proyecto y seguidamente ejecutamos la Clase ModificaMuestraPedido. Esta es la salida al ejecutar la aplicación

Recorrer los subelementos de un elemento
Ahora vamos a recorrer cada uno de los artículos del pedido y los vamos a mostrar en la salida estándar de la siguiente forma

De esta forma vamos a ver como podemos acceder a los diferentes subelementos articulo que están anidados en el elemento articulos del documento pedido.xml
Para ello tenemos que ampliar la Clase ModificaMuestraPedido.
Nota: Para recordar la forma de iterar colecciones podemos echar un vistazo a la siguiente página Síntesis Foro Java SE - Como iterar colecciones con “foreach”
package paqjaxb;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.math.BigDecimal;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import jaxb.pedido.DireccionEEUU;
import jaxb.pedido.PedidoType;
import jaxb.pedido.Articulos;
import jaxb.pedido.Articulos.Articulo;
public class ModificaMuestraPedido {
public static void main(String[] args) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance("jaxb.pedido");
Unmarshaller u = jaxbContext.createUnmarshaller();
JAXBElement jaxbElement = (JAXBElement) u.unmarshal(
new FileInputStream("pedido.xml"));
PedidoType pedidoType = (PedidoType) jaxbElement.getValue();
DireccionEEUU direccionEEUU = pedidoType.getFacturarA();
direccionEEUU.setNombre("Julian Nader");
direccionEEUU.setCalle("25 Lake Street");
direccionEEUU.setCiudad("Mission Viejo");
direccionEEUU.setEstado("CA");
direccionEEUU.setCodigoPostal(new BigDecimal("92692"));
Articulos articulos = pedidoType....
List<Articulo> listaArticulos = articulos....
iterarColeccionForeach(listaArticulos);
Marshaller m = jaxbContext.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(jaxbElement, System.out);
} catch (JAXBException je) {
je.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
private static void iterarColeccionForeach(List<Articulo> lista) {
for (... articulo : lista){
System.out.println("-----------------------");
System.out.println(articulo....);
System.out.println(articulo....);
System.out.println(articulo....);
}
}
}
|
Compara tu código con la solución propuesta
Crear un nuevo documento XML a partir de las instancias de las Clases generadas por el compilador JAXB
Finalmente vamos a realizar los dos últimos cambios.
Uno de ellos consiste en pasar a mayúsculas el nombre de los productos de cada uno de los artículos y lo mostramos a través de la consola de la siguiente forma

El otro cambio consiste en crear un nuevo documento XML llamado pedidomodificado.xml que refleje todos los cambios realizados en las instancias del las Clases generadas por el compilador JAXB.

Para realizar estos dos cambios nos basamos en el siguiente código
package paqjaxb;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.math.BigDecimal;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import jaxb.pedido.DireccionEEUU;
import jaxb.pedido.PedidoType;
import jaxb.pedido.Articulos;
import jaxb.pedido.Articulos.Articulo;
public class ModificaMuestraPedido {
public static void main(String[] args) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance("jaxb.pedido");
Unmarshaller u = jaxbContext.createUnmarshaller();
JAXBElement jaxbElement = (JAXBElement) u.unmarshal(
new FileInputStream("pedido.xml"));
PedidoType pedidoType = (PedidoType) jaxbElement.getValue();
DireccionEEUU direccionEEUU = pedidoType.getFacturarA();
direccionEEUU.setNombre("Julian Nader");
direccionEEUU.setCalle("25 Lake Street");
direccionEEUU.setCiudad("Mission Viejo");
direccionEEUU.setEstado("CA");
direccionEEUU.setCodigoPostal(new BigDecimal("92692"));
Articulos articulos = pedidoType.getArticulos();
List<Articulo> listaArticulos = articulos.getArticulo();
iterarColeccionForeach(listaArticulos);
cambiarNombreProductosMayusculas(listaArticulos);
Marshaller m = jaxbContext.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(jaxbElement, System.out);
m.marshal(jaxbElement, ...));
} catch (JAXBException je) {
je.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
private static void iterarColeccionForeach(List<Articulo> lista) {
for (Articulo articulo : lista){
System.out.println("-----------------------");
System.out.println(articulo.getCodigoStock());
System.out.println(articulo.getNombreProducto());
System.out.println(articulo.getCantidad());
}
}
private static void cambiarNombreProductosMayusculas(List<Articulo> lista) {
for (Articulo articulo : lista){
System.out.println("-----------------------");
System.out.println(articulo.getCodigoStock());
articulo.setNombreProducto(articulo.getNombreProducto()....);
System.out.println(articulo.getNombreProducto());
System.out.println(articulo.getCantidad());
}
}
} |
Compara tu código con la solución propuesta