Duda parseo XML

0 votos
preguntado por cascabel (540 puntos) Ene 28, 2016 en XML
Buenas a todos!

Tengo un problemilla de cara a parsear un fichero XML.

La estructura del fichero es la siguiente:

<pre lang='xml'><?xml version="1.0" encoding="UTF-8"?>
<ventas>
<EJ_2010>
<volumen cod="M0976">
<enero>32</enero>
<febrero>23</febrero>
<marzo>13</marzo>
<abril>23</abril>
<mayo>40</mayo>
<junio>21</junio>
<julio>18</julio>
<agosto>15</agosto>
<septiembre>21</septiembre>
<octubre>34</octubre>
<noviembre>56</noviembre>
<diciembre>49</diciembre>
</volumen>
...
...
<volumen cod="M1245">
<enero>33</enero>
<febrero>56</febrero>
<marzo>59</marzo>
<abril>46</abril>
<mayo>54</mayo>
<junio>43</junio>
<julio>12</julio>
<agosto>16</agosto>
<septiembre>26</septiembre>
<octubre>48</octubre>
<noviembre>53</noviembre>
<diciembre>63</diciembre>
</volumen>
</EJ_2010>
</ventas>
El fichero viene reflejando las ventas en cada mes de distintos emplea

dos de la empresa. El problema que me surge es que no se como "partir" la linea de ya que volumen simboliza el nuevo empleado y luego cod simoliza cual es el código del mismo.

<pre lang='java'>public void startElement(String namespace, String sName, String qName, Attributes atrs) throws SAXException {
...
else if (qName.equals("volumen")) {
if (qName.equals("cod")) {

....

}
Pero esta opcion de anidar el if no funciona, lo comprobe tras depurar por lo que el problema viene ahí y claro...luego ya se parsea mal y salta una excepción. Pero el problema viene de ahí seguro. ¿Se podria solucionar quizas utilizando alguno de los parametros que se llegan por cabecera a este método?¿Alguien me podría ayudar?

Muchas gracias de antemano.Un saludo a tod@s

9 Respuestas

0 votos
respondido por Torres (8,580 puntos) Ene 28, 2016
Buenas,

como te decía el problema está en que no tienes implementado el método characters, que es el que se encarga de leer el contenido de cada elemento.

SAX es mas eficiente que JDOM o que otras maneras de leer xml, porque no genera el arbol del xml en memoria si no que funciona por eventos. El startElement cuando comienza un elemento, el endElement cuando termina, etc.

En este caso te hace falta leer desde el characters hasta encontrar los números de las ventas en cada mes. No me gusta mandar código completo, pero con esto que te dejo aquí se almacena en el vector de Empleados, cada Empleado con sus ventas mensuales.



import java.util.Vector;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class LectorXMLVentas extends DefaultHandler {

    private Vector<Empleado> empleadosVentas;
    private Empleado emp;
    private Vector<Integer> ventas;

    /**
     * Método que crea el lector con un XMLReaderFactory
     *
     * @throws SAXException
     */

    public LectorXMLVentas() throws SAXException {
        empleadosVentas = null;
        emp = null;
        ventas = null;
    }

    /**
     * Método que determina que hay que hacer al comienzo del procesado del
     * documento xml
     *
     */

    public void startDocument() throws SAXException {

    }

    /**
     * Método que determina que hay hacer al terminar de leer una etiqueta
     *
     */
    public void endDocument() throws SAXException {

    }

    /**
     * Metodo que se encarga de tratar cada elemento en el inicio de la lectura
     * del mismo en el archivo XML.
     */

    public void startElement(String namespace, String sName, String qName,
            Attributes atrs) throws SAXException {
        if (qName.equals("ventas")) {// si es la linea de ventas creamos el
            // vector
            empleadosVentas = new Vector<Empleado>();
        } else if (qName.equals("EJ_2010")) {
            // no tenemos que hacer nada
        } else if (qName.equals("volumen")) {// si es volumen aqui empieza un
            // //nuevo empleado
            // y creamos el vector para ir metiendo sus ventas de //cada mes
            String codE = atrs.getValue("cod");
            emp = new Empleado(codE);
            ventas = new Vector<Integer>();// cuando terminemos de //leer
            // este elemento volcaremos este vector al //empleado
        }// else
        // sino estamos leyendo valores de ventas de meses, en este caso
        // //segun sea un mes u otro
        // almacenaVentas(atrs);
    }

    public void characters(char ch[], int start, int length) {

        String num = null;

        num = String.valueOf(ch, start, length);
        try {
            Integer ventaMensual = Integer.parseInt(num);
            ventas.add(ventaMensual);
        } catch (NumberFormatException e) {

        }
    }

    /**
     * Metodo que se encarga guardar la informacion necesaria al finalizar la
     * lectura de cada elemento del archivo XML.
     */

    public void endElement(String namespace, String sName, String qName)
            throws SAXException {
        if ("volumen".equals(sName)) {
            emp.fijaVentas(ventas);// le fijamos las ventas ya insertadas
            empleadosVentas.add(emp);// lo añadimos al vector
        }
    }

    /**
     * Método que devuelve el vector de empleados con los datos de las ventas
     * cargados
     *
     * @return vector de empleados
     *
     */

    public Vector<Empleado> dameEmpleadosCargaVentas() {
        return empleadosVentas;
    }
}

Espero que te sirva,

Un saludo


0 votos
respondido por cascabel (540 puntos) Ene 28, 2016
Buenas

Muchas gracias por responder...SI ayer a base de darle vueltas lo consegui. Y ahora cuando iba a postear ya vi que me habias respondido. Efectivamente gracias al metodo characters se solventa el problema.

Muchas gracias


0 votos
respondido por Torres (8,580 puntos) Ene 28, 2016
De nada y me alegro,

Un saludo


0 votos
respondido por cascabel (540 puntos) Ene 28, 2016
Puedo poner el codigo completo pero pienso que no te servirá de ayuda. Lo del getValue es cierto para una linea como la primera de las que puse.

 Ahora bien para una línea de estilo a la segunda no sirve debido que no se puede hacer el getValue del qName.

No obstante te pongo el codigo:

public class LectorXMLVentas extends DefaultHandler{

    private Vector<Empleado> empleadosVentas;
    private Empleado emp;
    private Vector<Integer> ventas;

    /**
     * Método que crea el lector con un XMLReaderFactory
     *
     * @throws SAXException
     */

    public LectorXMLVentas() throws SAXException {
        empleadosVentas=null;
        emp=null;
        ventas=null;
    }

    /**
     * Método que determina que hay que hacer al comienzo del procesado del documento xml
     *
     */

    public void startDocument() throws SAXException {

    }

    /**
     * Método que determina que hay hacer al terminar de leer una etiqueta
     *
     */
    public void endDocument() throws SAXException {

    }

    /**
     * Metodo que se encarga de tratar cada elemento en el inicio de la lectura del mismo en el
     * archivo XML.
     */

    public void startElement(String namespace, String sName, String qName, Attributes atrs) throws SAXException {
        if(qName.equals("ventas")){//si es la linea de ventas creamos el vector
             empleadosVentas = new Vector<Empleado>();
        }
        else if (qName.equals("EJ_2010")) {
                //no tenemos que hacer nada
        }
        else if (qName.equals("volumen")) {//si es volumen aqui empieza un //nuevo empleado
                //y creamos el vector para ir metiendo sus ventas de //cada mes
                String codE = atrs.getValue("cod");
                emp = new Empleado(codE);
                ventas = new Vector<Integer>();//cuando terminemos de //leer
                    //este elemento volcaremos este vector al //empleado
                }
        else //sino estamos leyendo valores de ventas de meses, en este caso //segun sea un mes u otro
            almacenaVentas(atrs);
        }

    /**
     * Método privado que se encarga de almacenar las ventas de los distintos meses
     *
     * @param atrs atributos del XML
     *
     */

    private void almacenaVentas(Attributes atrs) {
        //ocgemos el valor del mes, lo convertimos a entero y lo almacenamos en el vector de ventas
        String valorEne = atrs.getValue("enero");
        int venEne = Integer.parseInt(atrs.getValue("enero"));
        ventas.add(venEne);
        int venFeb = Integer.parseInt(atrs.getValue("febrero"));
        ventas.add(venFeb);
        int venMar = Integer.parseInt(atrs.getValue("marzo"));
        ventas.add(venMar);
        int venAbr = Integer.parseInt(atrs.getValue("abril"));
        ventas.add(venAbr);
        int venMay = Integer.parseInt(atrs.getValue("mayo"));
        ventas.add(venMay);
        int venJun = Integer.parseInt(atrs.getValue("junio"));
        ventas.add(venJun);
        int venJul = Integer.parseInt(atrs.getValue("julio"));
        ventas.add(venJul);
        int venAgo = Integer.parseInt(atrs.getValue("agosto"));
        ventas.add(venAgo);
        int venSep = Integer.parseInt(atrs.getValue("septiembre"));
        ventas.add(venSep);
        int venOct = Integer.parseInt(atrs.getValue("octubre"));
        ventas.add(venOct);
        int venNov = Integer.parseInt(atrs.getValue("noviembre"));
        ventas.add(venNov);
        int venDic = Integer.parseInt(atrs.getValue("diciembre"));
        ventas.add(venDic);
        emp.fijaVentas(ventas);//le fijamos las ventas ya insertadas
        empleadosVentas.add(emp);//lo añadimos al vector
    }

    /**
     * Metodo que se encarga guardar la informacion necesaria al finalizar la lectura de cada elemento del
     * archivo XML.
     */

    public void endElement(String namespace, String sName, String qName) throws SAXException{

    }

    /**
     * Método que devuelve el vector de empleados con los datos de las ventas cargados
     *
     * @return vector de empleados
     *
     */

    public Vector<Empleado> dameEmpleadosCargaVentas() {
        return empleadosVentas;
    }
}
Todo el proceso funciona perfectamente hasta que llegar al metodo almacenaVentas y claro como ya comente las lineas no son iguales y es ahí donde casca(porque probe a solo devolver el vector con los codigos de los empleados y los saca todos bien...lo que si soy capaz de leer). A ver si ahora me explique un poco mejor y alguien da con la solucion.

Muchas gracias de antemano y gracias por responder.

Un saludo.


0 votos
respondido por Torres (8,580 puntos) Ene 28, 2016
0 votos
respondido por cascabel (540 puntos) Ene 28, 2016
Tengo que utilizar el SAX por motivos de eficiencia...

Probablemente sea lo que tu dices...pero no se como hacerlo...


0 votos
respondido por cascabel (540 puntos) Ene 28, 2016
Ya lo solvente.

Ahora lo que me trae un poco de cabeza es que no soy capaz de leer los datos de cada uno de los meses...

Si tienes que leer una linea de este estilo: <volumen cod="M0976"> con algo de este estilo lo puedes conseguir:

public void startElement(String namespace, String sName, String qName, Attributes atrs) throws SAXException {
...
if (qName.equals("volumen")) {
        String codE = atrs.getValue("cod");
...
}
pero la linea es asi: <enero>32</enero>

y si intento hacer algo del tipo:

public void startElement(String namespace, String sName, String qName, Attributes atrs) throws SAXException {
...
int venEne = Integer.parseInt(atrs.getValue("enero"));
...
}
No consigo nada...porque no esta "dentro" de la etiqueta...

A ver si alguien me echa un cable...

Muchas gracias a todos.

Un saludo


0 votos
respondido por Torres (8,580 puntos) Ene 28, 2016
Si pones el código completo puede ser de ayuda, pero básicamente algo representará al elemento en cuestión y tendrá un getValue().

Algo por el estilo nodo.getValue()...


0 votos
respondido por Torres (8,580 puntos) Ene 28, 2016
Buenas!

Partir la linea? tendrás que acceder a cod que un atributo no un elemento en si mismo.

Te recomiendo JDOM, es muy sencillo de usar

http://www.jdom.org/docs/faq.html


Preguntas relacionadas

0 votos
0 respuestas
preguntado por davidlo04 (120 puntos) Ene 11, 2017 en XML
0 votos
0 respuestas
0 votos
2 respuestas
preguntado por Maria120 (120 puntos) Ene 28, 2016 en XML
0 votos
1 respuesta
preguntado por neo (120 puntos) Ene 28, 2016 en XML
0 votos
1 respuesta
preguntado por Goxver (120 puntos) Ene 28, 2016 en XML
Bienvenido a Dudas de Programación, donde puedes hacer preguntas y recibir respuestas sobre los problemas más frecuentes de los lenguajes de programación, frameworks de desarrollo y bases de datos que utilices. Foro de Línea de Código
...