1 / 26

Simple API for XML

XML. Simple API for XML. Introducción. ¿Cómo maneja la información representada en XML un programa? Requiere módulo parser  Lee fichero y crea representación en memoria (objetos, variables, …) ¿Qué alternativas tenemos? Podemos parsear “a pelo” el XML

merton
Download Presentation

Simple API for XML

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. XML Simple API for XML

  2. Introducción • ¿Cómo maneja la información representada en XML un programa? • Requiere módulo parser  Lee fichero y crea representación en memoria (objetos, variables, …) • ¿Qué alternativas tenemos? • Podemos parsear “a pelo” el XML • Problemas  Consideraciones UNICODE, substitución de ENTITIES, gestión namespaces, … • Reinvención de la rueda • Utilizar parsers XML (xerces, saxon, msxml, etc.) • Existen dos tendencias principales • Procesamiento en base a eventos • Procesamiento en árbol

  3. Procesamiento en base a eventos • El parser analiza el documento XML de forma secuencial • Puede pararse para insertar ENTIDADES de DTD o ir validando documento de acuerdo a DTD/Schema • Según lee el documento va generando eventos. • Por ejemplo, consideremos este fragmento XML: • <libro><titulo>Don Quijote de la Mancha</titulo><autor>Miguel de Cervantes</autor></libro> • El parser podría generar los siguientes eventos: startElement:libro startElement:titulo content: Don Quijote de la Mancha endElement:titulo startElement:autor content:Miguel de Cervantes endElement:autor endElement:libro

  4. Procesamiento en base a eventos (II) • Puede haber muchos eventos, no sólo apertura y cierre de un elemento • Definición de un nuevo namespace, atributo encontrado, comentario, processing instruction, etc. • Los parsers orientados a eventos no mantienen memoria del documento • Sólo generan eventos  usuario de la API debe mantener el estado si lo necesita • Parser sencillo  Aplicación compleja • Limitaciones • Edición y construcción de documentos • Recorrido aleatorio del documento p.e. al aplicar XPaths • Ventajas • Simplicidad • Rapidez • Consumo de memoria reducido • Ideales para leer documentos que no cambian  P.e. ficheros de configuración

  5. Procesamiento en base a modelo árbol • Los documentos XML describen estructuras en árbol  Representación en memoria de un árbol alternativa más lógica • Existen diferentes modelos de árbol para los documentos XML ligeramente diferentes • XPath • DOM (Document Object Model) API del W3C (Representación de objetos en memoria) • XML Infoset también del W3C • Extensiones para aplicaciones particulares (SVG) • El más extendido y conocido  DOM

  6. Procesamiento en base a modelo árbol (II) • Ventajas modelos de árbol • El programa puede acceder de forma nativa a elementos XML • Objetos XML  Objetos Java, objetos C++, estructuras C, etc. • No hay limitaciones en cuanto al recorrido • Podemos volver hacia atrás, ir directamente al final, etc. • Sencillo modificar documento • Se añaden nuevos objetos al árbol cuyas ramas se construyen típicamente en base a listas  Modelo preferido para editores XML, browsers • Inconvenientes • Grandes requerimientos de memoria  un documento XML en memoria puede ocupar. Varias veces tamaño fichero XML. • P.e. consideremos elemento: <a/> (4 bytes UTF-8) • Representación Java podría traducirse a objeto Element (Name(String),AttributeList,NamespaceList)  Podría irse a 200 bytes • ¿Cuánto ocuparía la representación de un fichero de 120 MB? • Inviable para procesamiento de grandes volúmenes de información  Alternativas mixtas, trucos, etc.

  7. APIs de mayor nivel • Generalmente toda API de manejo información XML se basa por debajo en modelo basado en árbol o basado en eventos • Incluso las implementaciones basadas en árbol se suelen crear sobre APIs en base a eventos • Es habitual que ofrezcan las dos posibilidades • Casos como las APIs de manejo de documentos SVG (Scalable Vector Graphics) añaden extensiones propias a APIs DOM para adaptarse mejor a sus características concretas • En la programación no tenemos por qué quedarnos con un único modelo • Es habitual combinar ambos.

  8. ¿Qué es SAX? • SAX significa Simple API for XML  API basada en eventos • Web  http://www.saxprojet.org • Originariamente fue una especificación para Java • Se ha convertido en un estándar de facto • Portada a multitud de plataformas. Existe soporte para SAX, aparte de Java en: • MSXML 3.0  A través de objeto COM (Visual Basic, C, C++, …) • Pascal • Perl • Python 2.0 • C (Xerces-C), C++ • Xerces  API Parser Java y otros lenguajes del proyecto Apache. Soporta entre otros • Interfaces SAX version 2 (actual) • DOM level 3 • JAXP 1.2  Java API for XML Processing • Validación XML Schema

  9. ¿Cómo puedo utilizar SAX? • SAX es una API estándar • No obstante cada implementación puede variar ligeramente • Java es uno de los lenguajes más utilizados para la programación XML • Java proporciona la API JAXP  Java API for XML Processing • Proporciona interfaces comunes para utilizar: SAX, DOM y APIs para XSLT • Abstrae del fabricante. • Equivalente a JDBC o ADO (MS) para BBDD • ¿Cómo uso entonces una API SAX en Java? • Directamente a través del driver • A través de la API SAX independiente del driver • A través de la API JAXP

  10. ¿Qué necesito para empezar? • Java 1.1 o superior • Vamos a utilizar JDK 1.5 • Un parser compatible SAX2 instalado en el classpath • Usaremos Xerces http://xml.apache.org/xerces-j/ • La distribución SAX2 para Java • Viene integrado en JDK 1.5 • Opcionalmente • Entorno de desarrollo Java. • Usaremos NetBeans http://www.netbeans.org • Instalamos todos los componentes necesarios …

  11. Iniciando un proyecto • Abrimos Netbeans • Creamos un nuevo proyecto web: • File New Project • Escojemos el tipo: Java Application • Especificamos los datos del proyecto: • Le damos un nombre al proyecto  EjemploSAX • Para Project Directory ponemos uno por ejemplo en el Escritorio llamado CursoXML • Podemos dejar MainClass vacío o le damos un nombre EjemploSAX1

  12. Familiarización entorno • Edición • Podemos navegar por el árbol de la izquierda por las fuentes y ficheros de configuración • Con el botón derecho podemos crear nuevas clases,ficheros jsp,… en el directorio indicado • Ejecución target principal del proyecto: • Compila todas las fuentes no compiladas o modificadas y empaqueta librerías en jars y crea fichero war • Build  Build Main Project • El objetivo que ejecutaremos será jar • Construcción parcial: • Si desplegamos el fichero “makefile” del proyecto de ant (build.xml) dentro src y pulsamos con el botón derecho podemos ejecutar cada target por separado (compilación, javadoc, etc.).

  13. Creando la aplicación • Creamos un paquete: p.e. es.captiva.cursoxml • Creamos una clase que se extienda de org.xml.sax.helpers.DefaultHandler: import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.XMLReaderFactory; import org.xml.sax.XMLReader; public class EjemploSAX1 extends DefaultHandler { public EjemploSAX1 (){ super(); } } • Le añadimos un método main que va a instanciar un lector (XMLReader) a partir de una factoría XMLReaderFactory. public static void main (String args[]) { XMLReader xr = XMLReaderFactory.createXMLReader(); }

  14. Creando la aplicación (II) • La clase XMLReaderFactory es una clase factoría que busca la implementación de parser adecuado. • ¿Cómo determina la fábrica qué parser debe escoger? • Variable de entorno: org.xml.sax.driver • ¿Cómo le asignamos un valor? • Desde la llamada al programa java -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser EjemploSAX1 sample.xml • Desde dentro del programa System.setProperty("org.xml.sax.driver", "org.apache.xerces.parsers.SAXParser"); • También podríamos en su lugar crear una instancia del driver directamente  Perderíamos flexibilidad XMLReader xr = new org.apache.xerces.parsers.SAXParser();

  15. Asociación gestor eventos • Una vez que disponemos de un lector necesitamos asociarle el handler, que es la clase que recibirá los eventos. • Utilizamos los métodos • setContentHandler() Para asociar clase que recibe los eventos relacionados con lectura del documento (encontrado apertura elemento, etc.) • setErrorHandler() Para asociar los eventos de error en el documento • ¿Qué ocurre si hay un evento de un tipo y no hay un handler asociado? • Se ignora el evento • Podría ocurrir un error y que el driver acabara sin decir nada.

  16. Asociación gestor eventos (II) • En nuestra aplicación el gestor de eventos es la propia clase (EjemploSAX1): public static void main (String args[]){ XMLReader xr = XMLReaderFactory.createXMLReader(); EjemploSAX1 handler = new EjemploSAX1(); xr.setContentHandler(handler); xr.setErrorHandler(handler); } • Sólo queda invocar al parser, que hay que alimentarlo con datos XML. El parser recibe estos datos en una clase org.xml.sax.InputSource. • Si miramos la documentación de la API (doc en Xerces) vemos que un InputSource puede crearse a partir de un InputStream o Reader, más adecuado para leer contenido textual.

  17. Alimentando al parser • ¿Cómo va a recibir los datos nuestra aplicación? • Indicando nombres de ficheros XML en línea de comandos. • Creamos un java.io.FileReader (subclase de Reader para ficheros) por cada fichero de entrada. for (int i = 0; i < args.length; i++) { System.out.println(“Procesando fichero “ + args[i] + “...”); FileReader fr = new FileReader(args[i]); xr.parse(new InputSource(fr)); } • El método parse() es el que llama al parser y empieza a procesador documentos XML.

  18. Gestión de eventos • Esta aplicación por ahora no hace nada • Necesitamos gestionar los eventos • Escribir métodos dentro de nuestra clase que reciben eventos. • Métodos: • startDocument() • endDocument() • startElement(String uri, String name, String qName, Attributes atts) • endElement(String uri, String name, String qName) • characters (char ch[], int start, int length) • Otros métodos  Ver API DefaultHandler

  19. Gestión de eventos (II) • Nuestra aplicación va a: • Contar el número de nodos elemento • Imprimir inicio y cierre de elemento • Imprimir texto dentro de los elementos • Para el contador implementamos variable miembro de EjemploSAX1: • int numElementos; • Implementamos la función miembro llamada al inicio del documento dentro de : public void startDocument () { this.numElementos = 0; System.out.println("********** Inicio del documento **********"); } • Y la de fin de documento, donde imprimimos el número de elementos encontrados: public void endDocument () { System.out.println("************ Fin del documento ***********"); System.out.println(">>>>>>> Se han procesado: " + this.numElementos + " elementos"); }

  20. Gestión de eventos (III) • Al comenzar un elemento imprimimos su nombre e incrementamos el contador: public void startElement (String uri, String name, String qName, Attributes atts) { this.numElementos ++; if (uri.length() == 0) System.out.println(“Inicio elemento: " + qName); else System.out.println(“Inicio elemento: {" + uri + "}" + name); } • Cabe destacar el parámetro uri. En caso de tratarse de un elemento definido en un namespace el parser pasa la URI de dicho namespace. • El parámetro qName es la versión cualificada del nombre del elemento  P.e.: xhtml:body • Y evento para fin del elemento: public void endElement(String uri, String name,String qName) { if (uri.length() == 0) System.out.println("Fin elemento: " + qName); else System.out.println("Fin elemento: {" + uri + "}" + name); }

  21. Gestión de eventos (IV) • Por último el evento de texto. Para que se vea más claro substituimos tabuladores y nuevas lineas por “\t”, “\n”, “\r”: public void characters (char ch[], int start, int length){ System.out.print(“Texto: \""); for (int i = start; i < start + length; i++) { switch (ch[i]) { case '\\': System.out.print("\\\\"); break; case '"': System.out.print("\\\""); break; case '\n': System.out.print("\\n"); break; case '\r': System.out.print("\\r"); break; case '\t': System.out.print("\\t"); break; default: System.out.print(ch[i]); break; } } System.out.print("\"\n"); }

  22. Últimos retoques • Completamos la importación de todos las clases que necesitamos para que no se queje el compilador: package es.captiva.xml.ejemplos; import java.io.FileReader; import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.XMLReaderFactory; import org.xml.sax.XMLReader; import org.xml.sax.InputSource; import org.xml.sax.Attributes; • Compilamos el proyecto y obtenemos EjemploSAX1.jar en el directorio dist

  23. Ejecución • Copiamos EjemploSAX1.jar a un directorio con ficheros XML (cualquiera de prácticas pasadas) y ejecutamos: java –jar EjemploSAX1.jar fich1.xml fich2.xml fich3.xml • Vemos la salida del programa. Funciona y no debería. ¿Por qué? • No hemos especificado ningún driver • La explicación  JDK incluye un driver que utiliza por defecto

  24. Ejecución (II) • Volvemos a ejecutar especificando el driver de Xerces: java –Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser –jar EjemploSAX1.jar fich1.xml fich2.xml fich3.xml • Ahora obtenemos el error: Exception in thread "main" java.lang.ClassNotFoundException: org.apache.xerces.parsers.SAXParser at org.xml.sax.helpers.XMLReaderFactory.loadClass(XMLReaderFactory.java:189) at org.xml.sax.helpers.XMLReaderFactory.createXMLReader(XMLReaderFactory .java:150) at es.captiva.xml.ejemplos.EjemploSAX1.main(EjemploSAX1.java:88) • No ha encontrado la clase del driver especificada. Copiamos xercesImpl.jar a %JAVA_HOME%\jre\lib\ext

  25. Ejercicio • Probar con los ficheros XML de prácticas anteriores • Buscar ficheros con y sin namespaces • Modificaciones ejercicio • Añadir soporte para atributos (número de atributos totales e impresión de los que encuentre) • Añadir soporte para NOTATIONS y PROCESSING INSTRUCTIONS

  26. Referencias • SAX • http://http://www.saxproject.org • Xerces • http://xml.apache.org/xerces-j/ • Javadoc API XML • http://java.sun.com/xml/jaxp/dist/1.1/docs/api/

More Related