domingo, 12 de febrero de 2012

Uso de XML, serializar y deserializar


XML es un lenguajes de modelado de datos o, lo que es lo mismo, es un lenguaje que permite definir un modelo de datos. Se podría decir que es un fichero que guarda los datos como si fuera una base de datos y se utiliza cuando se necesite. Se puede usar para que una aplicación use datos de otra, como un RSS. Por ejemplo, un archivo xml sería:
<?XML>
<clientes>
  <usuario>
    <nombre>Juan</nombre>
  </usuario>
</cliente>
SAX es una librería estandar en Java que permite el manejo de archivos para serializar y deserializar los ficheros XML. Estos dos conceptos se definirían de esta forma:
  • Serialización: Coge objetos de memoria y los registra en un fichero físico.
  • Deserialización: Lee el fichero interpretando los nodos y los pasa a objetos.(continuar, poniendo código de serialización y deserialización)
Veamos ahora un ejemplo:

Tenemos una web, donde se suben imágenes y los usuarios las votan. Queremos que, cada vez que un usuario vota, en un archivo XML se guarden las 5 más votadas para luego mostrarlas.  Para ello, en primer lugar necesitamos la clase Imagen:
package ria;
/**
 *
 * @author Tarde
 */
public class Imagen {
 //ATRIBUTOS
 private int id;
 private String nombre;
 private String ruta;
 private String descripcion;
 private int votos;

 public Imagen(){

 }
 public Imagen(String nombre,String ruta,String descripcion,int votos){
 this.nombre=nombre;
 this.ruta=ruta;
 this.descripcion=descripcion;
 this.votos=votos;

 }
/**
 * @return the id
 */
 public int getId() {
 return id;
 }
/**
 * @param id the id to set
 */
 public void setId(int id) {
 this.id = id;
 }
/**
 * @return the nombre
 */
 public String getNombre() {
 return nombre;
 }
/**
 * @param nombre the nombre to set
 */
 public void setNombre(String nombre) {
 this.nombre = nombre;
 }
/**
 * @return the ruta
 */
 public String getRuta() {
 return ruta;
 }
/**
 * @param ruta the ruta to set
 */
 public void setRuta(String ruta) {
 this.ruta = ruta;
 }
/**
 * @return the descripcion
 */
 public String getDescripcion() {
 return descripcion;
 }
/**
 * @param descripcion the descripcion to set
 */
 public void setDescripcion(String descripcion) {
 this.descripcion = descripcion;
 }
/**
 * @return the votos
 */
 public int getVotos() {
 return votos;
 }
/**
 * @param votos the votos to set
 */
 public void setVotos(int votos) {
 this.votos = votos;
 }

 public int subirImagen(){
 int s;
 MySQL mysql=new MySQL("flickr","//localhost","root", "forman");
 mysql.inicializarBD();
 s=mysql.insertar("INSERT INTO imagenes (nombre,ruta,descripcion,votos,idUsuario) VALUES ('"+getNombre()+"','"+getRuta()+"','"+getDescripcion()+"','0','"+getId()+"');");
 mysql.cerrarBD();

 return s;
 }
}
También necesitamos la clase que va a serializar las imagenes (ImagenSerializator.java). En esta se especifica que imágenes va a contener el XML, que son el resultado de una consulta:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ria;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
import java.sql.ResultSet;
import java.sql.SQLException;
import ria.MySQL;
/**
 *
 * @author Tarde
 */
public class ImagenSerializator {
 String path;
 List myData;
 Document dom;

 public ImagenSerializator(String path) {
 myData = new ArrayList();
 this.path = path;
 init();
 createDocument();
 }
 private void init(){
 try{
 MySQL mysql=new MySQL("flickr","//localhost","root","forman");
 ResultSet rs;
 mysql.inicializarBD();
 mysql.consultar("SELECT nombre,ruta,descripcion,votos FROM imagenes ORDER BY votos DESC LIMIT 5");
 rs=mysql.getResultSet();
 while(rs.next()){
 myData.add(new Imagen(rs.getString("nombre"),rs.getString("ruta"), rs.getString("descripcion"),rs.getInt("votos")));
 }
 }catch(SQLException ex){

 }

 }
 private void createDocument() {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 try {
 DocumentBuilder db = dbf.newDocumentBuilder();
dom = db.newDocument();
}catch(ParserConfigurationException pce) {
 System.out.println("Error while trying to instantiate DocumentBuilder " + pce);
 System.exit(1);
 }
 }

 public void createDOMTree(){
Element rootEle = dom.createElement("galeria");
 dom.appendChild(rootEle);
Iterator it = myData.iterator();
 while(it.hasNext()) {
 Imagen b = (Imagen)it.next();
Element ImagenEle = createImagenElement(b);
 rootEle.appendChild(ImagenEle);
 }

 }

 private Element createImagenElement(Imagen b){
Element ImagenElem = dom.createElement("imagen");
 //StockEle.setAttribute("id", b.getID());
Element nombreElem = dom.createElement("nombre");
 Text nombreText = dom.createTextNode(b.getNombre());
 nombreElem.appendChild(nombreText);
 ImagenElem.appendChild(nombreElem);
Element rutaElem = dom.createElement("ruta");
 Text rutaText = dom.createTextNode(b.getRuta());
 rutaElem.appendChild(rutaText);
 ImagenElem.appendChild(rutaElem);
Element descripcionElem = dom.createElement("descripcion");
 Text descripcionText = dom.createTextNode(b.getDescripcion());
 descripcionElem.appendChild(descripcionText);
 ImagenElem.appendChild(descripcionElem);

 Element votosElem = dom.createElement("votos");
 Text votosText = dom.createTextNode(String.valueOf(b.getVotos()));
 votosElem.appendChild(votosText);
 ImagenElem.appendChild(votosElem);
return ImagenElem;
}
public void Serialization(){
try
 {
 OutputFormat format = new OutputFormat(dom);
 format.setIndenting(true);
XMLSerializer serializer = new XMLSerializer(
 new FileOutputStream(new File(path + "/galeriaMIO.xml")), format);
serializer.serialize(dom);
} catch(IOException ie) {
 ie.printStackTrace();
 }
 }
}
Ahora, cuando se quiera crear el archivo XML, es decir, cuando el usuario vota, se llamaría a serializar.jsp, que contiene el siguiente código:
<%@page import="ria.ImagenSerializator"%>
<%
//Context Path
String path = application.getRealPath("/");
//Instance
ImagenSerializator stockSer = new ImagenSerializator(path);
//Prepare tree
stockSer. createDOMTree();
//Save to file
stockSer.Serialization();
request.getRequestDispatcher( "/index.jsp" ).forward( request, response );
%>
El archivo XML se guarda por defecto  build/web, dentro del proyecto.
Ahora, cuando el usuario quiera ver el top five de imágenes más votadas, deserializará este XML y lo mostrará en pantalla. Para ello haremos uso de dos clases que guardarán cada uno de los elementos del XML y lo dejarán listos para poder manipularlos. A estas clases no es necesario que le hagas ningún cambio, simplemente añádelas a tu proyecto y listo:
MyElement.java
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ria;
import org.xml.sax.Attributes;

public class MyElement implements java.io.Serializable {

 String uri;
 String localName;
 String qName;
 String value=null;

 Attributes attributes;

 public MyElement() {}

 public MyElement(String uri, String localName, String qName, Attributes attributes) {
 this.uri = uri;
 this.localName = localName;
 this.qName = qName;
 this.attributes = attributes;
 }

 public String getUri() {
 return uri;
 }

 public String getLocalName() {
 return localName;
 }

 public String getQname() {
 return qName;
 }

 public Attributes getAttributes() {
 return attributes;
 }

 public String getValue() {
 return value;
 }

 public void setValue(String value) {
 this.value = value;
 }

}

MySAXParseBean.java
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ria;
import java.io.*;
import java.util.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
public class MySAXParseBean extends DefaultHandler implements java.io.Serializable {
 private String text;
 private Vector vector = new Vector();
 private MyElement current = null;

 public MySAXParseBean() {}

 public Vector parse(String filename) throws Exception {

 SAXParserFactory spf = SAXParserFactory.newInstance();
 spf.setValidating(false);

 SAXParser saxParser = spf.newSAXParser();

 // create an XML reader
 XMLReader reader = saxParser.getXMLReader();

 FileReader file = new FileReader(filename);

 // set handler
 reader.setContentHandler(this);

 // call parse on an input source
 reader.parse(new InputSource(file));

 return vector;
 }

 // receive notification of the beginning of an element
 public void startElement (String uri, String name, String qName, Attributes atts) {

 current = new MyElement(uri, name, qName, atts);

 vector.addElement(current);
 text = new String();
 }

 // receive notification of the end of an element
 public void endElement (String uri, String name, String qName) {

 if(current != null && text != null) {
 current.setValue(text.trim());
 }
 current = null;

 }

 // receive notification of character data
 public void characters (char ch[], int start, int length) {

 if(current != null && text != null) {
 String value = new String(ch, start, length);
 text += value;
 }
 }

}
Y ya por último, en verTopFive.jsp, se mostrarán las imágenes y sus votos, haciendo uso de MyElement:
<%@page import="ria.MySQL"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="ria.ImagenSerializator"%>
<%@page import="ria.MyElement"%>
<%@ page import="java.util.*" %>
<%@ page import="org.*" %>
<html>
<head>
<title>Top Five Galeria</title>

</head>

<body>
 <jsp:useBean id="saxparser" class="ria.MySAXParseBean" />

<%
HttpSession sesion=request.getSession(false);
if(sesion.getAttribute("idLogeado")!=null){
 String idLogeado=sesion.getAttribute("idLogeado").toString();
 int iniciado=1;
 String path = application.getRealPath("/");
 Collection stocks = saxparser.parse(path + "galeriaMIO.xml");
Iterator ir = stocks.iterator();
 //mysql.consultar("SELECT idimagenes,nombre,ruta,descripcion,votos,idUsuario FROM imagenes;");
 //rst=mysql.getResultSet();
 %>

<h3>Top 5</h3>
 <table border="1">
 <tr>
 <td>
 <h4>Imagen</h4>
 </td>
 <td>
 <h4>Votos</h4>
 </td>
 <td></td>
 <td></td>
</tr>
 <tr>
 <%
 int contador=0;
 while(ir.hasNext()) {
 MyElement element = (MyElement) ir.next();
 String tag = element. getQname();

 if(tag.equals("ruta")) { %>
<td>
 <img src="./imagenes/<%= element.getValue() %>" >

 </td>
 <%
 } else if (tag.equals("votos")) {
 %>
 <td>
 <%= element.getValue() %>
 </td>
 </tr>
 <%
 }
 }

 %>
 </table>

 <a href="index.jsp">Volver</a>
 <%
}else{
 %>
 No estas logeado para entrar en esta página. <a href="index.jsp">Inicia sesión</a>
 <%
 }
 %>

 </body>
</html>

No hay comentarios:

Publicar un comentario