Encuesta

¿Qué piensas de la adquisición de Sun por parte de Oracle?

30-06-2009 - 177 votos

Destacados Agenda

Más eventos |

(1)

XML desde java hecho fýcil: JDOM

16/02/2002 00:00 teso

JAVA+XML = JDOM (Parte 1)

Introducción

JDOM es un API para leer, crear y manipular documentos XML de una manera sencilla y muy intuitiva para cualquier programador en Java, en contra de otras APIs tales como DOM y SAX, las cuales se idearon sin pensar en ningún lenguaje en concreto, de ahí que resulte un poco incomodo su utilización.

En este articulo exploraremos un poco el API, crearemos una pequeña aplicación que lea un documento XML y sacaremos de él aquellas partes que nos interese. Para abrir boca, imagínate este trozo de XML:

...
<site>javahispano</site>
...

Se imagina acceder al texto del elemento site de esta manera:

String nombre = site.getText();

¿Te gusta? Esto es JDOM.

Donde se encuentra JDOM

Para comenzar haremos una visión de pájaro para ver donde encajamos JDOM en un pequeño esquema.

Antes de seguir adelante permitirme una aclaración: DOM y SAX son dos especificaciones que como tal no podemos trabajar con ellas, pero si con las implementaciones de dichas especificaciones, es decir, los parsers: Xerces, XML4j, Crimson, Oracle's parsers,...

Pues bien un ultimo apunte, la API JDOM no es un parser, de echo, usa un parser para su trabajo, JDOM "solo" nos aporta una capa de abstracción en el tratado de documentos XML facilitándonos bastante la tarea como veremos enseguida, de echo no tendremos que ser unos gurus de DOM y SAX para poder trabajar con XML desde Java.

Donde conseguir JDOM

En www.jdom.org podremos descargar tanto el API como la documentación que necesitemos. Antes de que se me olvide, la licencia es open source. :-)

Como JDOM fue diseñado usando List y Map de la API Java 2 Collections, tendremos que utilizar el jdk 1.2 o si usas el jdk 1.1 deberás de instalar la librería Collections.

Estructura de JDOM

El API está formado por 5 packages. De entre ellas comentamos lo siguiente que será mas que suficiente para utilizar el API.

  • El package org.jdom destacamos las clases: Document que representará el documento XML, Element que representará el elemento o etiqueta que forma el documento, y la clase Attribute que como bien imaginaras representa los atributos que puedan tener los elementos.
  • El package org.jdom.adapters albergará todas las clases adaptadoras (ver patrón de diseño Adapter, Thinking in patterns) ya que no todos los parsers DOM tienen la misma API. Mas tarde quedara mas claro su función.
  • El package org.jdom.input albergara las clases builder para construir los documentos XML.
  • El package org.jdom.output albergara las clases que utilizaremos para dar salida a nuestra clase Document.

Un poco de teoría

Como dije al principio del articulo JDOM usaba los parsers para hacer su trabajo, pues bien, para decirle a JDOM que parser utilizar utilizaremos uno de los siguientes métodos:

public SAXBuilder(String parserClass, boolean validation)

El primer parámetro es el parser que vamos a utilizar, por defecto se utilizará el parser Xerces.

El segundo parámetro es para decirle si queremos que el parser cumpla sus obligaciones de validación.

public DOMBuilder(String adapterClass, boolean validation)

El primer parámetro es la clase adaptadora que vamos a utilizar para el parser que utilizaremos .

El segundo parámetro es igual que el del SAXBuilder.

Ahora al builder le daremos la orden de parsear el documento XML con el método build(), cuya forma es:

Document build(File file) 

Muy bien ya tenemos el documento almacenado en la clase Document. Finalmente vamos a aprender unos cuantos métodos mas para recuperar la información que deseemos:

Este método pertenece a la clase Document

Element getRootElement(); //cojer el nodo raiz del documento.

Estos métodos pertenecen a la clase Element:

String getText();
//Capturar el texto de una etiqueta o elemento.
List getChildren(); 
//Coger todos los elementos que cuelgan del Element.
List getChildren(String nombre);
 //Coger todos los elementos que tengan ese nombre
List getMixedContent();
 //Para recuperar todo(comentarios, PIs, elementos,...) 
 // de lo que cuelga del Element.
Element getChild (String nombre);
 //Coger el primer hijo que tenga ese nombre.
String getAttributeValue(String nombre);
 //Coger el valor del atributo que pasamos como parámetro.
Attribute getAttribute(String nombre); 
//Coger el atributo que tenga ese nombre y para recuperar 
//el valor de ese atributo se 
//utilizaría el método del attribute: String getValue();

Nuestro primer programa

Dado el siguiente documento XML:

<?xml version="1.0"?>
<liga tipo="Champions League">
  <equipo>
    <club valoracion="10" ciudad="Bilbao">Athletic Club Bilbao</club>
    <presidente>Uria</presidente>
    <plantilla>
      <nombre>Julen Guerrero</nombre>
      <nombre>Joseba Etxeberria</nombre>
      <nombre>Ismael Urzaiz</nombre>
    </plantilla>
  </equipo>
  <equipo>
    <!-- no os piqueis ;-) -->
    <club valoracion="5" ciudad="Madrid">Real Madrid</club>
    <presidente>Mandamas</presidente>
    <plantilla>
      <!-- no pongo nombres propios por si acaso -->
      <nombre>Bota de oro</nombre>
      <nombre>Milloneti</nombre>
      <nombre>Canterano quemado</nombre>
    </plantilla>
    <conextranjeros/>
  </equipo>
  <arbitros>
    <nombre>No doy una</nombre>
    <nombre>Rafanomejodas</nombre>
  </arbitros>
</liga>

Vamos a hacer un programa que lo lea y nos muestra cierta información. Este sería el codigo:

import java.io.*;
import java.util.*;
import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;

public class Ejemplo {

  public static void main(String[] args) {
     try {
        SAXBuilder builder=new SAXBuilder(false); 
        //usar el parser Xerces y no queremos 
        //que valide el documento
        Document doc=builder.build("liga.xml");
        //construyo el arbol en memoria desde el fichero
        // que se lo pasaré por parametro.
        Element raiz=doc.getRootElement();
        //cojo el elemento raiz
        System.out.println("La liga es de tipo:"+
                    raiz.getAttributeValue("tipo"));
        //todos los hijos que tengan como nombre plantilla
        List equipos=raiz.getChildren("equipo");
        System.out.println("Formada por:"+equipos.size()+" equipos");
        Iterator i = equipos.iterator();
        while (i.hasNext()){
            Element e= (Element)i.next();
            //primer hijo que tenga como nombre club
            Element club =e.getChild("club"); 
            List plantilla=e.getChildren("plantilla"); 
            System.out.println
                          (club.getText()+":"+"valoracion="+
                           club.getAttributeValue("valoracion")+","+
                           "ciudad="+club.getAttributeValue("ciudad")+","+
                           "formada por:"+plantilla.size()+"jugadores");
             if (e.getChildren("conextranjeros").size()==0)
              System.out.println("No tiene extranjeros");
             else  System.out.println("Tiene extranjeros");

        }
        // Dejamos de mano del lector el sacar el nombre 
        //de los arbitros, animate!!
     }catch (Exception e){
        e.printStackTrace();
     }
  }
}

Conclusión

Como hemos visto el leer documentos XML y sacar la información de dicho documento es un trabajo realmente fácil con JDOM, como veremos en el siguiente articulo el crear documentos con esta API no es mucho mas complicado.

Javier Teso, actualmente está cursando 5º de Ing. Informática de San Sebastián.
Para cualquier duda o comentario: jte_job_ARROBA_hotmail.com ó jabotxa_ARROBA_latinmail.com
Volver a actualidad

Etiquetas: xml

Comentarios: 47

  • ctosov 05/02/2003 00:00

    Javier te felicito por tu articulo pero necesito de tu ayuda.
    Baje el .jar de jdom para hacer el ejemplo que aqui presentas.. Podrias decirme como tengo que hacer para que mi jdeveloper funcione correctamente con esas librerias?? gracias

  • chispy 25/02/2003 00:00

    Buen articulo, jdom es muy util pero un poco lento.
    Una observación con animo +, debes añadir al codigo la parte necesaria para mostrar el nº de jugadores y sus nombre,

  • caroli 12/11/2003 00:00

    Muy útil para comenzar, ahora ya me atrevo yo solita . Muchas gracias Javier!!! Carol

  • vroso29 15/11/2004 00:00

    Excelente para iniciarse, ahora ya sé hacer un montón de cosas con él.
    Estaría bien agregar a todos los usuarios cómo crear un XML asociado con un DTD, que también es bastante fácil.
    Gracias por tu tiempo empleado en hacer el artículo

  • ferchik 27/07/2005 00:00

    Muy bueno el artículo. Sobre todo por su simpleza.
    Gracias.
    F/

  • fernand74 26/09/2005 00:00

    Excelente articulo, muy util para aquellos que empezamos a conocer XML y Java.

  • juanargt 08/09/2006 00:00

    Muy bueno el artículo la verdad muy facil de entender y de implementar, Gracias a gente como ustedes todo se hace un poco mas facil.

    Salute

  • zeruel_angel 29/11/2006 00:00

    EXCELENTE tutorial y MUY claro el ejemplo! felicidades! "ctosov" Si usas el NETBEANs, te lo bajas de la pagina de SUN te olvidas de instalar los paquetes y pluggins por que trae la mayoria, eso si, mientras arranca el programa toamte un cafecito

  • genomacl 28/02/2007 00:00

    Esta muy bueno tu árticulo, te felicito.
    Necesito resolver un problemilla y quiero saber si alguien sabe como hacerlo.

    Tanto el parseador DOM como SAX al momento de hacer el builder espera un File como parametro para parsear. Ahora mi pregunta es la siguiente:

    Tengo una consulta sql con salida XML, el XML queda almacenado en un string y eso lo necesito parsear sin la necesidad de grabar en un file(esto es por seguridad).... SI ALGUIEN SABE LE AGRADECERIA EXPLICARME.
    GRACIAS

  • Anónimo 08/10/2007 04:50

     

    Excelente estabamos buscando algo asi porque no sabiamos como comenzar ahora sera mas facil, muy util,¡GRACIAS! ****** MHJ_Jhónatan

  • Anónimo 16/10/2007 00:53

    Gracias estimado =D me a servido mucho =) aprendi en un par de minutos a leer un archivo cml gracias a tu articulo =)

  • Anónimo 23/10/2007 18:31

    Excelente esto lo estaba buscando y me fue muy util.

     

    gracias..... R.Berroa

  • Anónimo 15/11/2007 19:13

    UNa pregunta en el caso q tengas un xml de esta estructura:

     

     

    Cual es tu nombre?

     

    Pancho

    Juan

     

     

     

    Cual es tu pais?

     

    MExico

    ESpaña

     

     

     

     

    en este caso si lo lees con JDOm, como pones un indice a los nodos, osea ahi hay 2 nodos preguntas.

    Como podrias crear un indice en el cual le digas quiero ver la informacion "opciones", pero unicamente de preguntas[1] que en este caso es Mexico y ESpaña.

     

    En realidad no habia contemplado eso, se pude hacer?

  • Anónimo 15/11/2007 19:15

    UNa pregunta en el caso q tengas un xml de esta estructura:

         
            Cual es tu nombre? 
            
                   Pancho
                  Juan 
            
        
         
            Cual es tu pais? 
            
                   MExico
                  ESpaña 
            
        

     

     

    en este caso si lo lees con JDOm, como pones un indice a los nodos, osea ahi hay 2 nodos preguntas.

    Como podrias crear un indice en el cual le digas quiero ver la informacion "opciones", pero unicamente de preguntas[1] que en este caso es Mexico y ESpaña.

     

    En realidad no habia contemplado eso, se pude hacer?

  • Anónimo 28/11/2007 23:22

    pues te tengo dos soluciones muy faciles..

    1.No lo hagas.

    2.Pegate un tiro.

    :) y tus poblemas se acabaran....

  • Anónimo 03/12/2007 04:17

    muy bueno

     

    JC

  • Anónimo 19/12/2007 22:33

    Muy informativo, aunque las imagenes no se visualizan... lo que hubiera sido interesante es un ejemplo desde 0 usando algun IDE para una mejor visualizacion.

     Saludos

  • Anónimo 30/01/2008 02:12

    Muy buena explicacion, y el ejemplo genial, aunque le voy mas al Barza.. XD

  • Anónimo 01/02/2008 00:37

    HOLA UN EJEMPLO JDOM PARA CREAR  UN XML DESDE CERO.GRACIAS

  • Anónimo 18/02/2008 14:38

    El articulo es tremendamente util muchas gracias

    queria saber si es posible tratar un fichero como el que pego

    lo que no se es como coger esto

      

     y los valores que tiene  DocumentTitle,FechaCatalogacin etc

    es que como no es un tag de tipo <> ...

    no se como cogerlo

    este


    http://filenet.com/namespaces/wcm/appint/integration/1.0">
    executeSearch
    0
    Success



     

  • Anónimo 14/03/2008 16:04

    Buen articulo, me ayudo bastante.

    ¡Gracias!

  • Anónimo 23/03/2008 19:05

    Esta muy bueno gracias :D, no sabia que hacer

  • Anónimo 12/04/2008 14:22

    Me ha sido de mucha ayuda, gracias.

  • Anónimo 18/04/2008 01:18

    me gustaria ver un ejemplo con jdom pero para eliminar un nodo por que he hecho uno pero solo me elimina el contenido del nodo a la hora de hacer una busqueda y preguntar cual es el nodo que quiero eliminar.

  • Anónimo 03/05/2008 00:49

    el codigo no devuelve, la cantidad de jugadores por plantilla, solo devueve 1, cuando en realidad el ejemplo muestra 3 jugadores por plantilla, pero en general muy bueno el aporte se te agradece

  • Anónimo 04/05/2008 08:31

    Me ha sido muy util, gracias

  • Anónimo 06/05/2008 16:16

    De Miguel

    Muy bueno el árticulo, creo que me va a ser de mucha ayuda.

    Muy buen trabajo, gracias y seguid así

  • Anónimo 12/05/2008 05:16

    Genio, me iniciaste en esto! y voy entendiendo muchas cosas gracias a esos ejemplos, te debo una. Suerte y segui haciendo estas cosas!

    p/d:no podia no agradecerte!

  • Anónimo 14/05/2008 00:28

    Hola el articulo es muy bueno solo que tengo una pregunta mira te pongo el ejemplo y haber si me entiendes:

     

     

     

     

     

     

     

     

     

    ojala me puedas contestar estoy algo desesperado. Gracias

  • Anónimo 29/05/2008 18:01

    Buenas, ya te felicite anteriormente por el aporte. ahora me surgio una duda/inconveniente, ya que necesito pasar un archivo XML, como parametro de un metodo para usarlo de constructor. Alguno sabe como se hace esto?

    Gracias Saludos!

  • Anónimo 04/06/2008 12:32

    No consigo que funciones. Soy novato en esto y seguro que ese es el problema.

    Trabajo con Eclipse 3.3.2.

    Me he bajado jdom-1.1.zip. Lo he descomprimdo y he añadido a las librerias los ficheros "jar" que se encuentran en la carpeta /bin:

    ant.jar

    jaxen-core.jar

    jaxen-jdom.jar

    saxpath.jar

    xalan.jar

    xerces.jar

    xml-apis.jar

    Me sigue dando un error en rojo a la hora de importar las librerias:

    import org.jdom.*;
    import org.jdom.input.*;
    import org.jdom.output.*;

    Por favor, ayuda

  • Anónimo 04/06/2008 12:41

    Ya lo he solucionado. La librería que había que añadir es:

    build/jdom.jar

  • Anónimo 13/06/2008 00:02

    como hago para que me lea el archivo dandole la dirección. Por ejemplo C:\Mis Documentos\ejemplo.xml ?

  • Anónimo 18/06/2008 23:32

    Saludos amigos,

    Tengo 2 preguntas:

    1. ¿Donde pongo fisicamente la libreria JDOM que he descargado? , ¿en /BIN o en que parte?

    Soy nuevo en esto del Java.

    2. Tengo un servidor de Sockeckts para FLASH que hice para un chat, todo funciona bien en local (el servicio levantado)  usando la pelicula SWF directamente con el Flash Player pero lo bueno viene despues... Cuando lo trato de conectarme al servidor usando un Browser no se puede conectar en consola me aparece que el cliente SI se conecta pero inmediatemante despues pierde la conexion. 

    ¿Alquien sabe a que se debe este problema de desconexion?

     Saludos y excelente sitio.

    Ralph Moran

  • Anónimo 24/06/2008 13:29

    Muy bueno el documento, limpio y claro, y por poner ese ejemplo t mereces un 10.

    AUPA ATHLETIC !!!

    iKaTZ

  • Anónimo 24/06/2008 16:48

    Muy bueno, y bien explicado, gracias por el material publicado.

     

    Ricardo Martinez

  • Anónimo 04/07/2008 00:50

    hola muy bueno de verdad, estoy tratando de hacer lo siguiente:

     Leer desde un xml a una variable y que esa variable pueda ser usada en otras partes del codigo algo asi:

      private static void xml(String[] args)
          {
         try {
            SAXBuilder builder=new SAXBuilder(false);
            Document doc=builder.build("conf.xml");
            Element raiz=doc.getRootElement();
            String tipo= raiz.getAttributeValue("tipo");
         }catch (Exception e){
            e.printStackTrace();
         }
      }

     

    y que luego en otro 

    private static void otro(String[] args)
         tipo
      } 

     

    pueda usar la cadena tipo o otra variable muchas gracias

  • Anónimo 04/07/2008 00:51

    hola muy bueno de verdad, estoy tratando de hacer lo siguiente:

     Leer desde un xml a una variable y que esa variable pueda ser usada en otras partes del codigo algo asi:

      private static void xml(String[] args)
          {
         try {
            SAXBuilder builder=new SAXBuilder(false);
            Document doc=builder.build("conf.xml");
            Element raiz=doc.getRootElement();
            String tipo= raiz.getAttributeValue("tipo");
         }catch (Exception e){
            e.printStackTrace();
         }
      }

     

    y que luego en otro 

    private static void otro(String[] args)
         tipo
      } 

     

    pueda usar la cadena tipo o otra variable muchas gracias

  • Anónimo 06/07/2008 08:05

    hola estoy tratando de interpretar un XML en un movil para esto utilizo un metodo que recibe como parametro un String que en si es el XML, se que seria mas facil primero guardarlo en un archivo, pero lo que pasa es que tiene que funcionar en diferentes tipos de celulares y al poner la ruta del archivo donde quiero que se guarde en el movil al parecer no me deja crear una carpeta en el celular para poder guardarlo ahi, si lo quiero guardar en la raiz del celular tampoco me deja, si escojo una carpeta que ya exista en el celular por ejemplo "Mis imagenes" no todo los celulare tinen esa carpeta o almenos no la misma ruta para llegar a ella, por lo cual obte por guardar el contenido del XML en un String y de ahi interpretarlo. pero tengo un problema, este es el metodo que utilizo y no se porque no entra al ELSE que tiene como comentario "NO ENTRA AQUI" alguien me podria ayudar??

    public void interpretar(String cadena){       
            int i,j,x,y,opcd;
            String cad2,pregunta,opc;
            boolean band=false;
            cad2="";       
            x=0;
            y=1;
            //cuestionario.append("hola"+"\n"+"adios");
            while (y<(cadena.length()-20) && band==false){           
                cad2+=cadena.substring(x, y);             
                if(cadena.substring(x, y).equals("/")){
                    if(!cadena.substring(x+1,y+1).equals("c")){                   
                        if (cad2.indexOf("") > 0) {                                                    
                            i = cad2.indexOf("")+7;
                            j = cad2.indexOf(""*/);
                            pregunta= cad2.substring(i,j);
                            grupos[cont]=new ChoiceGroup(pregunta, ChoiceGroup.EXCLUSIVE);                    
                        }else{
                            if (cad2.indexOf("") > 0) {                           
                                i = cad2.indexOf("")+6;
                                j = cad2.indexOf(""*/);
                                opc= cad2.substring(i,j);
                                opcd=grupos[cont].append(opc, null);
                                grupos[cont].setSelectedIndex(opcd, true);
                            }else{
                                if (cad2.indexOf("") > 0) {
                                    i = cad2.indexOf("")+6;
                                    j = cad2.indexOf(""*/);
                                    opc= cad2.substring(i,j);
                                    grupos[cont].append(opc, null);
                                }else{
                                    if (cad2.indexOf("") > 0) {
                                        i = cad2.indexOf("")+6;
                                        j = cad2.indexOf(""*/);
                                        opc= cad2.substring(i,j);
                                        grupos[cont].append(opc, null);
                                    }else{
                                        if (cad2.indexOf("") > 0) {                                        
                                            i = cad2.indexOf("")+6;
                                            j = cad2.indexOf(""*/);
                                            opc= cad2.substring(i,j);
                                            grupos[cont].append(opc, null);
                                            cont++;                               
                                        }
                                    }
                                }
                            }
                        }                   
                        cad2="";
                        x++;
                        y++;
                        }else{ 
                        /*NO PASA POR AQUI
                            destroyApp(false);
                                notifyDestroyed();
                            break;*/
                            band=true;
                        }
                    }else{               
                        x++;
                        y++;
                    }
                }
                /*for (int iter = 0; iter < cont; iter++) {
                    destroyApp(false);
                                            notifyDestroyed();
                    cuestionario.append(grupos[iter]);           
                }*/       
                Display.getDisplay(this).setCurrent(cuestionario); 
            }

  • Anónimo 21/09/2008 10:57

    Wosquex Excelente..... no tengo otra cosa que decir..... demasiado bueno para ser cierto.... grax man

  • Anónimo 30/11/2008 04:48

    Muy simple, ayuda bastante

  • Anónimo 01/12/2008 04:34

    Hola a todos, usando el mismo ejemplo de liga.xml, el recorrido se puede hacer de forma mas rapida utilizando un foreach:

             List equipos=raiz.getChildren("equipo");
            System.out.println("Formada por: "+equipos.size()+" equipos");
            
            for (Object temp : equipos){
                //vemos el "equipo"
                Element e= (Element)temp;
                //nodo hijo de "equipo" que tenga como nombre "club"
                Element club =e.getChild("club");
                //todos los hijos de "equipo" que tengan como nombre "jugadores"
                List jugadores=e.getChildren("jugadores");
                System.out.println (club.getText()+": "+"valoracion= " + club.getAttributeValue("valoracion") + ", "+
                               "ciudad= "+club.getAttributeValue("ciudad")+", "+ "formada por: "+jugadores.size()+" jugadores");
                //si existe un hijo de "equipo" con el nombre "conextranjeros"
                if (e.getChildren("conextranjeros").size()==0)
                  System.out.println("No tiene extranjeros");
                else 
                  System.out.println("Tiene extranjeros");
            }
      Fijense que de esta forma no es necesario crear un objeto Iterator ni un while... resulta un poco mas sencillo...  xD

  • Anónimo 21/01/2009 19:27

    Me fue de gran ayuda, realmente no sabía ni como empezar hasta que encontré este artículo, desde ese momento me he vuelto una experta en XML. Muchas gracias.

     

    Gina.

  • Anónimo 13/02/2009 07:48

    Que buena página, muchas gracias gracias, yo igual estaba en cero, pero con esta ayuda me abren un gran panorama, gracias por explicarlo de una manera sencilla y clara.

     

  • Anónimo 24/03/2009 23:12

    Muy buena la explicacion y muy bueno el ejemplo, Muchas gracias

  • Anónimo 24/03/2009 23:36

    Muy buena la explicacion y muy bueno el ejemplo, Muchas gracias, me a creado un gran interes esa combinacion XML + Java, eso es poder, y quiseradonde puedo conseguir la segunda parte. la que consiste en crear un archivo Xml. una vez mas gracias.

    tnricardo 

  • Anónimo 01/07/2009 19:17

    Excelente lo he entendido mu bien,

     Pienso usar esto para escribir desde mi aplicacion un canal rss gestionando el xml con lo que explicas de JDOM, lo recomiendas o sabes alguna forma que fuera mejor para generar canales rss ??

     

    muchas gracias un saludo javier!

    Victor

     

Escribe tu comentario

Sun Microsystem Logo NHT-Norwick Logo

© 2002-2007 Asociación javaHispano