G.Bordel >Docencia >TAP Técnicas Actuales de Programación (curso 2010-2011)
desprotegido Intro. desprotegido Temario desprotegido Calendario desprotegido RPF desprotegido Recursos protegido Práctica protegido Gest. Alum.
tema_anterior Tema 12: Java y XML tema_siguiente
  1. Lenguajes de marcas.
  2. XML en la actualidad..
  3. SAX, DOM, XSD, XSLT, XPATH... .
  4. Soporte Java para XML.

12.4- Soporte Java para XML

Procesamiento básico

La API básica de Java para el procesamiento de XML esta disponible en la edición estandar (JavaSE):

  • Java API for XML Processing (JAXP).

Los siguientes son algunos de los paquetes que implementan esta APIs:

  • Xerces: El parser SAX y DOM más popular.
  • Crimson XML: Otro parser SAX y DOM más rápido.
  • Xalan: la implementación de XSLT/XPath más popular.
  • Sparta XML: Una implementación rápida y pequeña de SAX y DOM con un subconjunto de XPath.


Otros procesamientos

El resto de APIs relacionadas con XML han ido integrandose dentro del marco de los web-services.

  • APIs fundamentales (core)
    • Java API for XML-Based Web Services (JAX-WS)
    • Java Architecture for XML Binding (JAXB)
  • API heredada
    • Java API for XML-based RPC (JAX-RPC).
  • Otras diversas...


XML en JavaSE 6.0:

javax.xml
javax.xml.bind
javax.xml.bind.annotation
javax.xml.bind.annotation.adapters
javax.xml.bind.attachment
javax.xml.bind.helpers
javax.xml.bind.util
javax.xml.crypto
javax.xml.crypto.dom
javax.xml.crypto.dsig
javax.xml.crypto.dsig.dom
javax.xml.crypto.dsig.keyinfo
javax.xml.crypto.dsig.spec
javax.xml.datatype
javax.xml.namespace
javax.xml.parsers
javax.xml.soap
javax.xml.stream
javax.xml.stream.events
javax.xml.stream.util
javax.xml.transform
javax.xml.transform.dom
javax.xml.transform.sax
javax.xml.transform.stax
javax.xml.transform.stream
javax.xml.validation
javax.xml.ws
javax.xml.ws.handler
javax.xml.ws.handler.soap
javax.xml.ws.http
javax.xml.ws.soap
javax.xml.ws.spi
javax.xml.xpath 
-------------------
org.w3c.dom
org.w3c.dom.bootstrap
org.w3c.dom.events
org.w3c.dom.ls
org.xml.sax
org.xml.sax.ext
org.xml.sax.helpers 

Procesamiento básico de XML - Ejemplos

Antes de nada:
La clase
java.util.Properties dispone de loadFromXML y storeToXML.

Ejemplo procesamiento SAX

Supongamos que tenemos un fichero que describe una asignatura como es el siguiente:


<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE asignatura [
<!ELEMENT asignatura (titulo, titulacion, curso, cuatrimestre, creditos, caracter, itinerario, idioma, profesores, url_temario,url_contenido,inicio)>
<!ELEMENT titulo (#PCDATA)>
<!ELEMENT titulacion (#PCDATA)>
<!ELEMENT curso (#PCDATA)>
<!ELEMENT cuatrimestre (#PCDATA)>
<!ELEMENT creditos (#PCDATA)>
<!ELEMENT caracter (#PCDATA)>
<!ELEMENT itinerario (#PCDATA)>
<!ELEMENT idioma (#PCDATA)>
<!ELEMENT profesores (#PCDATA)>
<!ELEMENT url_temario (#PCDATA)>
<!ELEMENT url_contenido (#PCDATA)>
<!ELEMENT inicio (#PCDATA)>
]>

<asignatura>
 <titulo>Técnicas actuales de programación</titulo>
 <titulacion>Ingeniería Electrónica</titulacion>
 <curso>2</curso>
 <cuatrimestre>2</cuatrimestre>
 <creditos>9</creditos>
 <caracter>Optativa</caracter>
 <itinerario>Informática</itinerario>
 <idioma>Español</idioma>
 <profesores>
  German Bordel
  Mikel Peñagarikano
 </profesores>
 <url_temario>http://www.ehu.es/p200-content/es/contenidos/asignatura/15916ingel202_310_2_2_2008/es_15916/es_fileasig_15916.html</url_temario>
 <url_contenido>http://gtts.ehu.es/German</url_contenido>
 <inicio>2 de octubre</inicio>
</asignatura>

Podremos "parsearlo" -como ejemplo- para introducirlo en un objeto que recoja esta información como el siguiente:


class Asignatura {

    String comentario;
    String titulo, titulacion, caracter, itinerario = "", idioma, urlTemario = "", urlContenido = "", inicio = "";
    int curso, cuatrimestre, creditos;
    String[] profesores;

    @Override
    public String toString() {
        String prof = "";
        for (String p : profesores) prof = prof + ", " + p;
        return "---------------------------------" +
                "\n" + titulo +
                "\nProfesores: " + prof.substring(2) +
                "\n(" + curso + " curso, " + cuatrimestre + " cuatrimestre), (" + creditos + " creditos), [" + idioma + "]" +
                "\nComienzo: " + inicio +
                "\nTemario: " + urlTemario +
                "\nWeb: " + urlContenido +
                "\n---------------------------------";
    }
}

La instanciación del parser y su ejecución es extremadamente sencilla (el "truco" esta en la clase que aportamos como segundo parámetro a la acción de "parseo" y que veremos más adelante)


import javax.xml.parsers.*;
import java.io.*;
import org.xml.sax.*;

public class SaxTest {

    static Asignatura asignatura = new Asignatura();

    public static void main(String[] s) throws Exception {
        File ficheroXML = new File("Asignatura.xml");
        javax.xml.parsers.SAXParserFactory pf = javax.xml.parsers.SAXParserFactory.newInstance();
        pf.setValidating(true);
        javax.xml.parsers.SAXParser parser = pf.newSAXParser();
        parser.parse(ficheroXML, new ParserDeAsignaturas(asignatura));

        System.out.println(asignatura);

    }
}

Y como decíamos, aquí está el procesamiento específico que hacemos de nuestro XML:


class ParserDeAsignaturas extends org.xml.sax.helpers.DefaultHandler {

    Asignatura g;
    StringBuffer sb = new StringBuffer();

    ParserDeAsignaturas(Asignatura g) {
        this.g = g;
    }

    private String extraeSimple(String s) {
        return s.trim();
    }

    private String[] extraeMultiple(String s) {
        String[] s1 = s.trim().split("\r\n|\n");
        int j = 0;
        for (int i = 0; i < s1.length; i++) if (!s1[i].trim().equals("")) s1[j++] = s1[i];

        if (j == 0) return null;
        String[] s2 = new String[j];
        for (int i = s2.length - 1; i >= 0; i--) s2[i] = s1[i].trim();
        return s2;
    }

    public void startElement(String uri, String localName, String qName, org.xml.sax.Attributes attributes) {
        sb = new StringBuffer();
    }

    public void characters(char[] ch, int start, int length) {
        sb.append(ch, start, length);
    }

    public void endElement(String uri, String localName, String qName) {

        try {
            if (qName.equals("titulo")) g.titulo = new String(sb).trim();
            if (qName.equals("titulacion")) g.titulacion = extraeSimple(new String(sb));
            if (qName.equals("curso")) g.curso = Integer.parseInt(new String(sb));
            if (qName.equals("cuatrimestre")) g.cuatrimestre = Integer.parseInt(new String(sb));
            if (qName.equals("creditos")) g.creditos = Integer.parseInt(new String(sb));
            if (qName.equals("caracter")) g.caracter = extraeSimple(new String(sb));
            if (qName.equals("itinerario")) g.itinerario = extraeSimple(new String(sb));
            if (qName.equals("idioma")) g.idioma = extraeSimple(new String(sb));
            if (qName.equals("profesores")) g.profesores = extraeMultiple(new String(sb));
            if (qName.equals("url_temario")) g.urlTemario = extraeSimple(new String(sb));
            if (qName.equals("url_contenido")) g.urlContenido = extraeSimple(new String(sb));
            if (qName.equals("inicio")) g.inicio = extraeSimple(new String(sb));
            if (qName.equals("comentario")) g.comentario = extraeSimple(new String(sb));
        } catch (Exception ex) {
            System.out.println("ERROR (Handler) *************************************");
            ex.printStackTrace();
        }
    }

    public void error(SAXParseException ex)
            throws SAXException {
        System.out.println("ERROR (Parser) *************************************");
        ex.printStackTrace();
    }

    public void fatalError(SAXParseException ex)
            throws SAXException {
        System.out.println("ERROR FATAL (Parser) ********************************");
        ex.printStackTrace();
    }
}

Ejemplo procesamiento DOM

El parser DOM se encarga de leer todo el XML y formar una estructura de objetos equivalente que es accesible como un "Document"

import javax.xml.parsers.*;
import org.w3c.dom.*"

//Cómo comenzar (ejemplo frente a un fichero)
import org.w3c.dom.*;
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("elFichero"));

//Ejemplos de acceso a elementos del fichero (ya objetos)
String cacheUrl=((Element)doc.getElementsByTagName("source").item(0)).getAttribute("cache");
String titulo=((Element)doc.getElementsByTagName("url").item(0)).getTextContent();


/**
 * Ejemplo de rutina: Dado un elemento, localiza un hijo con tag dado, con un valor específico en el tributo indicado
 */
Element getElementByAttributeValue(Element e, String nn, String attr, String av) throws Exception{
        NodeList nl=e.getElementsByTagName(nn);
        if (nl==null) return null;
        for (int i=0; i<nl.getLength(); i++) {
                Element  nle=(Element)(nl.item(i));
                String  s=nle.getAttribute(attr);
                if (s!=null && s.equals(av)) return nle;
                }
        return null;
}

Ejemplo procesamiento XSLT

El siguiente es unejemplo de una hoja de estilo XSLT:

<?xml version="1.0" encoding="UTF-8" ?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:date="http://exslt.org/dates-and-times" extension-element-prefixes="date">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />


<!-- ===============================================================================
 GENERAL STRUCTURE
================================================================================ -->
<xsl:template match="/">
    <resource
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://gtts.ehu.es/Ehiztari"
xsi:schemaLocation="http://gtts.ehu.es/Ehiztari http://gtts.ehu.es/Ehiztari/erd.xsd">
        <xsl:call-template name="processors" />
        <xsl:call-template name="source" />
        <xsl:call-template name="segmentation" />
        <!-- NOT APPLICABLE <xsl:call-template name="sectioning" /> -->
    </resource>
</xsl:template>

<!-- ===============================================================================
 PROCESSORS section 
================================================================================ -->
<xsl:template name="processors">
    <processors>
            <processor>
                <xsl:attribute name="agent">
            <xsl:value-of select="concat(/Trans/@scribe,'(Transcriber)')" />
                </xsl:attribute>
                <xsl:attribute name="date">
                <xsl:value-of select="/Trans/@version_date" />
                </xsl:attribute>
                <xsl:attribute name="info">
            <xsl:value-of select="concat('audio_filename: ',/Trans/@audio_filename,'; ')" />
            <xsl:value-of select="concat('version: ',/Trans/@version,'; ')" />
            <xsl:value-of select="concat('elapsed_time: ',/Trans/@elapsed_time,'; ')" />
                    </xsl:attribute>
            </processor>
            <processor agent="trs2erd xslt" >
                <xsl:attribute name="date">
                <xsl:value-of select="date:date-time()" />
                </xsl:attribute>
            </processor>
        </processors>
</xsl:template>

Ejemplo aplicación XSLT

Una xslt se puede aplicar con un paquete: en pricipio el mismo XALAN (xalan org.xml trans.xsl > out), pero hay muchos más (Saxon, xray2, ...).

La siguiente clase muestra cómo actuar desde Java:

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class ApplyXSLT {

    /** Constructor anulado */
    private ApplyXSLT() {}

    public static void main(String[] args) throws FileNotFoundException, TransformerException, TransformerConfigurationException {

        if (args.length !=3) {
            System.out.println("Formato: java ApplyXSLT <xslt> <xml origen> <xml destino>");
            System.exit(1);
        }

        Source xslt = new StreamSource(new FileInputStream(args[0]));
        Source xml = new StreamSource(new FileInputStream(args[1]));
        Result resultado = new StreamResult(new FileOutputStream(args[2]));

// Me hago con una factoria de transformadores, instancio el necesario y ejecuto
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer(xslt);
t.transform(xml, resultado);
    }

}

Siguiente Tema: 13- Ingeniería del Software


Plataforma de soporte a curso y contenidos (c) German Bordel 2005.