Hace algunos días me vi en el dilema de tener que utilizar archivos XML como almacenamiento temporal, estos archivos almacenaban los datos de varios objetos y por tanto tendría que tener un mapeador asociado a cada objeto. Viendo un poco mas el asunto me di cuenta que estos objetos se diferencian básicamente por los atributos que tienen. La conformación de los objetos no es de mucha importancia pues son simplemente objetos de transición, que no tienen ningún método complejo. Por lo tanto en lugar de hacer un generador especifico para cada objeto y como estaba un poco aburrido decidí hacer un generador XML universal.
El objetivo de esta mini librería es tener la posibilidad de convertir un objeto o conjunto de objetos cualquiera de Java en un xml estándar con todos los beneficios que implica. Si quieres conocer algo más obre algunas de las cualidades de XML puedes darte una vuelta por este link.
El principal logro que tiene este generador universal es poder convertir un objeto o una lista de objetos Java de cualquier tipo en un archivo XML. Claro con algunas limitaciones, entre las peores están que: los atributos del objeto deben ser del tipo String, es necesario seguir los estándares de creación de objetos recomendadas por Sun como que los atributos sean privados y la forma de acceder a estos atributos sea por medio de los respectivos get y set. Limitaciones que sin duda no son críticas pero con algo de tiempo estas podrían ser eliminadas y esta utilidad podría ser mejorada sin duda.
Este generador utiliza la librería xerces para la creación de documentos xml; misma que podremos descargar desde su página principal.http://xerces.apache.org/xerces-j/
Lo primero es inicializar los documentos y crear el nodo raíz que se utilizará
private void startDocumentXML() {
try {
// 1. Crear objeto DocumentBuilderFactory
DocumentBuilderFactory dbFactory = DocumentBuilderFactoryImpl.newInstance();
// 2. A partir del objeto DocumentBuilderFactory crear
// un objeto DocumentBuilder
DocumentBuilder docBuilder = dbFactory.newDocumentBuilder();
// 3. Generar el documento XML
documentXML = docBuilder.newDocument();
} catch (Exception e) {
System.out.println("Error : " + e);
}
// 4. Crear el elemento "descargas"
document = documentXML.createElement(getRootName());
// 5. Agregar al documento principal
documentXML.appendChild(document);
}
La idea principal es que la clase reciba una lista de objetos y esta sea capaz de iterar sobre la lista y haciendo uso de algunas propiedades más o menos avanzadas de java como ser Reflection poder encontrar los elementos que conformarán el documento xml.
private void populateDocumetnXML(List elements) {
Element nElement;
Element item;
// 1. Crear elemento
nElement = documentXML.createElement(getRootName());
// iteramos sobre la lista de objetos que se recibe se
//construirá un elemento por cada objeto recibido
for (int a = 0; a < elements.size(); a++) {
Object value = "";
Method met;
Class obj;
Field[] stra;
obj = elements.get(a).getClass();
stra = obj.getDeclaredFields();
// posteriormente obtenemos una lista con los atributos que tiene cada objeto
// y de forma similar creamos nuevos nodos por cada atributo del objeto
for (int i = 0; i < stra.length; i++) {
try {
// utilizamos algo de reflection para obtener los valores de los atributos
met = obj.getMethod(getterFind(stra[i].getName()), new Class[]{});
value = (String) met.invoke(elements.get(a), new Object[]{});
} catch (Exception ex) {
}
// Si este es el primer elemento le asignamos el nombre del
// objeto como nombre del nodo en XML y le añadimos el primer
// atributo como identificador de atributo al nodo
if (i == 0) {
String tempSt = obj.getSimpleName().toLowerCase();
// 1. Crear elemento
nElement = documentXML.createElement(tempSt);
// 2. Asignar un atributo
nElement.setAttribute(stra[i].getName(), "" + value.toString());
// 3. Añadir elemento al documento
document.appendChild(nElement);
} else {
// a. Crear item
item = documentXML.createElement(stra[i].getName());
// b. Asignar un dato al item
item.appendChild(documentXML.createTextNode(value.toString()));
// c. Aniadir el item
nElement.appendChild(item);
}
}
}
}
El método getterFind lo único que hace es devolver el método al que se accede para obtener el valor del atributo de algún objeto.
private String getterFind(String atName) {
atName = atName.replaceFirst(atName .substring(0, 1), atName.substring(0, 1).toUpperCase());
atName = "get" + atName;
return attributeName;
}
Ahora se utiliza el parser para generar el archivo XML con los datos generados anteriormente
private String generateTextXML() {
StringWriter strWriter = null;
XMLSerializer serializeXML = null;
OutputFormat ouputFormat = null;
try {
serializeXML = new XMLSerializer();
strWriter = new StringWriter();
ouputFormat = new OutputFormat();
// 1. Establecer el formato
ouputFormat.setEncoding(getEncodingXML());
ouputFormat.setVersion(getVersionXML());
ouputFormat.setIndenting(true);
ouputFormat.setIndent(4);
// 2. Definir un objeto donde se generara el codigo
serializeXML.setOutputCharStream(strWriter);
// 3. Aplicar el formato
serializeXML.setOutputFormat(ouputFormat);
// 4. Serializar documento XML
serializeXML.serialize(documentXML);
strWriter.close();
} catch (IOException ioEx) {
System.out.println("Error : " + ioEx);
}
return strWriter.toString();
}
Finalmente se guarda el archivo generado
private void saveDocumentXML(String texto) {
try {
OutputStream fout = new FileOutputStream(getFileName());
OutputStream bout = new BufferedOutputStream(fout);
OutputStreamWriter out = new OutputStreamWriter(bout, getEncodingJava());
out.write(texto);
out.flush();
out.close();
} catch (UnsupportedEncodingException e) {
System.out.println("Error encoding");
} catch (IOException e) {
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println("Error : " + e);
}
}
para probar el invento podemos utilizar temporalmente el método
public static void main(String args[]) {
// A. Crear el objeto(s) a Descarga
Descarga descarga = new Descarga("1", "Libs", "http://algo.org", "2546");
Descarga descarga2 = new Descarga("2", "Otros", "http://algo.org", "1654");
// User user = new User(1, "123", "Vladimir C", "Calle 149", "Cochabamba");
List elementList = new ArrayList();
elementList.add(descarga);
elementList.add(descarga2);
// elementList.add(user);
GenerateXML generator = new GenerateXML();
generator.generateXML(elementList);
}
Naturalmente necesitamos una clase con los atributos mencionados provistas ademas de sus métodos accesores.
Y el resultado de correr el main anterior es:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Root>
<descarga id="1">
<titulo>Libs</titulo>
<ruta>http://algo.org</ruta>
<hits>2546</hits>
</descarga>
<descarga id="2">
<titulo>Otros</titulo>
<ruta>http://algo.org</ruta>
<hits>1654</hits>
</descarga>
</Root>
Funciona genial para una lista de objetos del mismo tipo; pero que sucede cuando utilizamos más de un objeto en la lista? (descomenta las líneas que hacen referencia a la clase User en el main)
<?xml version="1.0" encoding="ISO-8859-1"?>
<Root>
<descarga id="1">
<titulo>Libs</titulo>
<ruta>http://algo.org</ruta>
<hits>2546</hits>
</descarga>
<descarga id="2">
<titulo>Otros</titulo>
<ruta>http://algo.org</ruta>
<hits>1654</hits>
</descarga>
<user id="1">
<ci>123</ci>
<fullName>Vladimir C</fullName>
<adress>Calle 149</adress>
<city>Cochabamba</city>
</user>
</Root>
Como se puede apreciar el comportamiento es muy bueno cuando se tiene diversos objetos en la lista.
El proyecto final está disponible para descargar desde el siguiente enlace : El mismo esta construido como proyecto Netbeans para su fácil revisión. Además se pueden manipular otros atributos referentes a la creacion del xml, por ejemplo la codificiación, el nombre deldocumento raiz. De la misma forma en el proyecto se cuenta con un pequeño loguer que guarda informacion en caso de haber existido algun error en la generación del XML
En este articulo podremos apreciar la forma de utilizar el archivo XML generado
Esta utilidad toma como base una similar(menor generica) publicada en este blog
Saludos cordiales en una siguiente entrada veremos el proceso de leer el XML para poblar los objetos Java.
Fuente: http://www.debugmodeon.com/item/247367/mapeando-java-objects-a-xml-o-generar-xml-desde-java