Zona HTML Zona Java Zona PHP Zona ASP Zona Bases de datos
-Tutoriales

El API JAXB


Construir Representaciones de Datos

Este capítulo explica cómo usar las clases que generamos en el capítulo anterior para:

  • Despempaquetar un documento XML en un árbol de contenido.
  • Ejemplarizar las clases para construir un árbol de contenido.
  • Validar nuestro árbol de contenido contra el DTD.
  • Empaquetar un árbol de contenido en un nuevo documento XML.
  • Añadir un arbol de contenido a otro árbol de contenido.

. El Ejemplar de Documento XML:march.xml

El documento march.xml es válido contra checkbook.dtd. Recordamos del capítulo Antes de Empezar: Fundamentos de XML que un documento XML debe tener un elemento raíz que incluya el resto de los elementos del documento. El elemento raíz del documento march.xml es el elemento transactions porque march.xml representa el conjunto de las transacciones para el mes de Marzo. Según lo mostrado aquí en march.xml, sólo teníamos un depósito, un cheque, y una transacción de reintegro en el mes de marzo:

<?xml version="1.0" encoding="US-ASCII"?> 
<;transactions> 
    <;deposit category=salary > 
        <;date>03-14-2001<;/date> 
        <;name>Me<;/name> 
        <;amount>3000.00<;/amount> 
    <;/deposit> 
<;check number="2" category="groceries"> 
    <;date>03-15-2001<;/date> 
    <;name>Conglomerate Foods<;/name> 
    <;amount>34.95<;/amount> 
    <;pending/> 
    <;memo>food<;/memo> 
    <;/check> 
    <;withdrawal>
        <;date>03-16-2001<;/date> 
       <;amount>20.00<;/amount> 
    <;/withdrawal> 
<;/transactions>

. Configurar Nuestra Aplicación

Antes de poder usar JAXB para construir representaciones de datos o trabajar con los datos, primero necesitamos cear una aplicación Java que realice estas funciones. Para configurar nuestra aplicación JAXB:

  1. Creamos un fichero llamado CheckbookApp.java
  2. Importamos estos paquetes:
    import java.io.*;
    import java.util.*;
    import javax.xml.bind.*;
    import javax.xml.marshal.*;
    

    Los dos últimos paquetes son parte del marco de trabajo de unión, que define los métodos unmarshal, marshal, y validate.

  3. Declaramos la clase CheckbookApp :
    public class CheckbookApp {
    }
    
  4. Inicializamos dos objetos Transactions:
    public static Transactions marchTrans = new Transactions();
    public static Transactions aprilTrans = new Transactions();
    

    Necesitaremos reutilizar estos objetos en nuestra aplicación.

  5. Dentro de CheckbookApp, creamos nuestro método main:
    public class CheckbookApp {
        public static void main(String args[]) throws Exception {
        }
    }
    

El fichero CheckbookApp.java está localizado en el directorio examples/checkbook de la descarga.

. Construir un Árbol de Contenido

JAXB nos permite construir un árbol de contenido de una de estas dos formas: despempaquetando un documento XML o ejemplarizando las clases generadas.

. Desempaquetar

Una vez que hayamos generado las clases del DTD que especifica un documento XML, podemos desempaquetar el documento en un árbol de contenido. En el directorio /examples/checkbook, se encuentra el fichero llamado march.xml, que contiene las transacciones escritas en el mes de marzo. Para desempaquetar este documento XML en un árbol de contenido en el fichero CheckbookApp.java:

  1. Creamos un metodo llamado buildTrees:
    public static void buildTrees() throws Exception {
    }
    
  2. En nuestro nuevo método leemos el fichero XML en un FileInputStream:
    File march = new File("march.xml");
    FileInputStream fIn = new FileInputStream(march);
    
  3. Llamamos al método unmarshal de Transactions, que es la clase que representa el elemento raíz transactions del checkbook.dtd:
    try {
    marchTrans = marchTrans.unmarshal(fIn);
    } 
    finally {
        fIn.close();
    }
    
  4. Llamamos al método buildTrees desde nuestro método main:
    buildTrees();
    

    En este punto, CheckbookApp genera un árbol de contenido desde march.xml. La sección Acceder al Contenido mostrará cómo manipular el contenido del árbol. La sección siguiente muestra cómo construir un árbol de contenido ejemplarizando las clases generadas.

. Ejemplarización

Si tenemos un DTD XML pero ningun ejemplar de documento XML válido especificado por el DTD, podemos crear un documento XML válido construyendo un árbol de contenido desde las clases derivadas y empaquetando el árbol en un documento XML. Supongamos que deseamos crear un árbol de contenido que representa una lista de transacciones para el mes de abril. Para construir este árbol de contenido con ejemplarización:

  1. En el método buildTrees, después de la llamada para desempaquetar el fichero march.xml, obtenemos la lista de entradas del objeto aprilTrans, creamos un nuevo objeto Check, representando el cheque para el alquiler del mes de abril:
    List aprilEntries = aprilTrans.getEntries();
    Check aprilRentCheck = new Check();
    CheckCategory aprilRent = CheckCategory.RENT;
    aprilRentCheck.setCategory(aprilRent);
    
  2. Seleccionamos el nombre de la entidad que recibe el cheque:
    aprilRentCheck.setName(Gilchrest Gardens Manor);
    
  3. Seleccionamos el número de cheque:
    aprilRentCheck.setNumber(51);
    

    Podemos pasar un int al método setNumber porque especificamos en el esquema de unión que la propiedad number acepta y devuelve un int.

  4. Seleccionamos la fecha para el cheque:
    aprilRentCheck.setDate(TransDate.parseDate(04-12-2001));
    

    Usamos el método parseDate de la clase TransDate que proporcionamos en el Capítulo anterior porque especificamos nuestro propio formato de fechas, que es:MM-dd-yyyy.

  5. Seleccionamos la cuantía del cheque:
    aprilRentCheck.setAmount(new java.math.BigDecimal(1500.00));
    

    Podemos pasar un java.math.BigDecimal al método setAmount porque especificamos en el esquema de unión que la propiedad amout acepta y devuelve un java.math.BigDecimal. Cuando comencemos a calcular el balance para el libro de cheques en el siguiente capítulo, veremos la ventaja de realizar estas conversiones de tipos.

  6. Seleccionamos el estado del cheque a pendiente:
    Pending pending = new Pending();
    aprilRentCheck.setPendVoidClrd(pending);
    
  7. añadimos el cheque a la lista de entradas del árbol de contenidos aprilTrans:
    aprilEntries.add(aprilRentCheck);
    

    El objeto Entry representa una lista de transacciones, que incluye cualquier número de depósitos, de cheques, y de reintegros. Las clases Deposit, Check, y Witdrawal implementan Entry, que representa las funciones comunes de estas tres clases. Después de que creemos un cheque, un depósito, o un reintegro, lo agregamos a la lista de entradas. Puesto que la lista es modificable, las transacciones que le agregamos se añaden automáticamente al árbol de contenido.

Ahora tenemos dos árboles de contenido: uno para las transaciones de Marzo, y otro para las transaciones de Abril. La siguiente sección explica como acceder al contenido de estos árboles.

. Acceder al Contenido

Tanto si construimos un árbol de contenido desempaquetando un documento de XML o ejemplarizando sus clases, tenemos acceso al contenido de la misma forma. Esta sección demostrará el acceso al contenido de los árboles de contenidos que creamos en la sección anterior. En el fichero march.xml, tenemos un cheque de la tienda de comestibles para "Conglomerate Fodds". Ahora nos hemos dado cuenta de que compramos en "Mom and Pop Foods" en su lugar. Necesitamos cambiar el nombre del receptor del cheque de la tienda de comestibles a "Mom and Pop Foods"

  1. Creamos un nuevo método llamado accessContent:
    public static void accessContent() {}
    
  2. En nuestro método accessContent, llamamos a getEntries sobre el objeto marchTrans:
    List entryList = marchTrans.getEntries();
    

    El entryList contiene todas las transaciones contenidas en el árbol de contenido que representa los datos de march.xml.

  3. Iteramos a través de la lista para encontrar las transaciones check:
    for(ListIterator i = entryList.listIterator(); i.hasNext(); ) {
        Entry entry = (Entry)i.next();
        if ( entry instanceof Check ){
    
  4. Obtenemos la categoría e cada entrada check que encontramos para determinar si el cheque de la categoría groceries:
    CheckCategory category = ((Check) entry).getCategory();
    if(category.equals(CheckCategory.GROCERIES)){
    
  5. Si el cheque pertenece a la catergoría groceries, seleccionamos el nombre del receptor a "Mom and Pop Foods" y añadimos los corchetes de cierre:
                ((Check)entry).setName(Mom and Pop Foods);
                break;
            }
        }
    }
    
  6. Llamamos al método accessContent desde el método main:
    accessContent();
    

Después de haber creado el árbol de contenido para las transacciones de Abril, nuestro casero nos informa de que ha aumentado el alquiler a $2000. Así pues, necesitamos cambiar la cantidad del cheque del alquiler en el árbol de contenido que representa las transacciones para el mes de Abril.

Para cambiar la cuantía del cheque del alquiler:

  1. En el método accessContent, obtenemos la lista de entrada, pero esta vez llamamos a getEntries sobre el objeto aprilTrans:
    List aprilEntries = aprilTrans.getEntries();
    
  2. Iteramos sobre la lista para encontrar el cheque del alquiler, y seleccionamos su cuantía a $2000:
    for(ListIterator i = aprilEntries.listIterator(); i.hasNext(); ) {
        Entry entry = (Entry)i.next();
        if ( entry instanceof Check ){
           CheckCategory category = ((Check) entry).getCategory();
           if(category.equals(CheckCategory.RENT)){
               entry.setAmount(new java.math.BigDecimal(2000.00));
           }
       }
    }
    

Observa en el último paso que no hemos tenido que forzar Entry a un Check para fijar la cuantía del cheque. Esto es porque especificamos en el esquema de unión que la cantidad es uno de los miembros del interface Entry porque es un elemento que comparten Check, deposit, y Withdrawal. Así pues, cualquier ejemplar de Entry tendrá una cuantía. En el paso 4 del primer conjunto de pasos, tuvimos que forzar la entry a un Check para fijar el nombre porque el nombre no es uno de los miembros del interface Entry. La razón por la que no especificamos Entry para contener un nombre es porque withdrawal no incluye name como uno de sus elementos.

Como hemos hecho cambios en los árboles de contenido, deberíamos asegurarnos de que nuestro árbol es válido antes de empaquetarlo. La siguiente sección explica cómo validar los árboles de contenido.

. Validación

Antes de empaquetar un árbol de contenido a un documento XML, debemos asegurarsnos de que el árbol de contenido es válido con respecto al DTD. Si utilizamos desempaquetamiento en vez de ejemplarización para construir el árbol de contenido, y no hemos modificado el árbol, no necesitamos validar antes de empaquetar porque el proceso de desempaquetamiento incorpora la validación. Si utilizamos la ejemplarización para construir el árbol, siempre necesitamos realizar explícitamente la validación antes de empaquetar. Hemos modificado ambos árboles de contenido en la sección anterior, y así que debemos validarlos antes de empaquetarlos.

Para validad ámbos árboles de contenido:

  1. Creamos un método llamado validateTrees:
    public static void validateTrees() throws Exception {}
    
  2. Dentro del método, llamamos a validate sobre marchTrans y aprilTrans :
    marchTrans.validate();
    aprilTrans.validate();
    
  3. Llamamos a validateTrees desde el método main:
    validateTrees();
    

. Empaquetar

Después de validar los árboles de contenido, estamos listos para empaquetarlos en nuevos documentos XML. Tanto si construímos un árbol de contenido usando desempaquetamiento o ejemplarización, empaquetamos un árbol de la misma forma. Para empaquetar los árboles de contenido:

  1. Creamos un nuevo método llamado marshalTrees:
    public static void marshalTrees() throws Exception {}
    
  2. En el nuevo método, creamos nuevos ficheros, para contener los contenidos actualizados de ámbos árboles:
    File march_new = new File(march_new.xml);
    File april_new = new File(april_new.xml);
    
  3. Creamos el obejto OutputStream para enviarlo al método marshal:
    FileOutputStream fMOut = new FileOutputStream(march_new);
    FileOutputStream fAOut = new FileOutputStream(april_new);
    
  4. Llamamos al método marshal sobre cada árbol:
    try {
        marchTrans.marshal(fMOut);
        aprilTrans.marshal(fAOut);
    } 
    finally {
        fMOut.close();
        fAOut.close();
    }
    
  5. Llamamos a marshalTrees desde el método main:
    marshalTrees();
    

Después de que recompilemos las clases y ejecutemos CheckbookApp, veremos los ficheros march_new.xml y april_new.xml en el directorio. Si comparamos march.xml con march_new.xml, encontraremos que la única diferencia entre los dos ficheros es el nombre del cheque de la tienda de comestibles, que modificamos. JAXB preserva la equivalencia entre un documento XML y el mismo documento XML formados desde su árbol de contenido. La siguiente sección muestra cómo agregar el contenido del árbol que representa las transacciones de Abril al árbol de contenido que representa las transacciones de Marzo.

. Añadir Árboles de Contenido

Puesto que un objeto en un árbol de contenido puede tener más de un padre, podemos añadir árboles de contenido juntos. Podemos emplear esta técnica para añadir las transacciones de Abril a las transacciones de Marzo antes de añadir las transacciones al libro de cheques como se mostrará en el siguiente capítulo. Para añadir AprilTrans a Trans:

  1. Creamos un nuevo método llamado appendTrees:
    public static void appendTrees() {}
    
  2. En el nuevo método, obtenemos la lista de entradas de cada objeto Transactions:
    List mEntries = marchTrans.getEntries();
    List aEntries = aprilTrans.getEntries();
    
  3. Usamos el método addAll de List, para añadir la lista completa de las transaciones de Abril a la lista de las transaciones de Marzo:
    mEntries.addAll(aEntries);
    
  4. Llamamos a appendTrees desde el método main:
    appendTrees();
    

El siguiente capítulo muestra cómo ampliar la clase Checkbook para proporcionar funcionalidades para añadir nuestras transaciones de Marzo y Abril a nuestro libro de cheques y hacer el balance.

 
Patrocinados
 

Copyright © 1999-2006 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad

Hospedaje web y servidores dedicados linux por Ferca Network