Para muchos es común asociar parsing de documentos XML con DOM o SAX, pero ¿StAX?… no les sonará muy familiar.
¿Qué es StAX?
StAX (Streaming API for XML) es la ultima API en formar parte de la familia JAXP (Java API for XML Processing, conformado por SAX, DOM, StAX y TrAX) y nos provee una alternativa a SAX y DOM para el procesamiento de documentos XML. La principal meta de StAX es otorgarle el control del parseo al programador exponiendo una API basada en un iterador simple. StAX nos permite lograr un alto rendimiento en la iteración, procesado y modificación de documentos XML sobretodo en entornos donde se disponga de poca cantidad de memoria y limitada capacidad de extensibilidad.
Comparación de StAX con los otras API’s de JAXP
Característica | StAX | SAX | DOM | TrAX |
---|---|---|---|---|
Tipo de API | Pull, streaming | Push, streaming | En memoria | Regla XSLT |
Facilidad de uso | Alta | Media | Alta | Media |
Capacidad XPath | No | No | Si | Si |
Eficiencia de CPU y memoria | Buena | Buena | Varia | Varia |
Solo hacia adelante | Si | Si | No | No |
Lee XML | Si | Si | Si | Si |
Escribe XML | Si | No | Si | Si |
Crear, Leer, Modificar, Borrar | No | No | Si | No |
Casos de uso de StAX
- Enlace de datos:
Marshalling/Unmarshalling de un documento XML. Procesamiento de documentos en paralelo y comunicación inalámbrica.
- Procesamiento SOAP:
Parsing de estructuras simples predecibles, parsing de representaciones de grafos con referencias hacia adelante, parsing de WDSL.
- Data source virtuales:
Ver datos almacenados en Bases de datos como XML, ver datos en objetos Java creados por enlace de datos XML (xml data binding), parseo de vocabularios XML específicos y procesamiento de XML canalizado.
StAX consta realmente de 2 distintas API:
- Cursor API: Representa un cursor con el cual se puede ir hacia adelante en un documento XML desde el principio hasta el final. Este cursor puede apuntar un elemento a la vez y siempre se mueve hacia adelante, nunca hacia atrás.
- Iterator API: Representa un flujo de un documento XML como un conjunto de objetos de eventos discretos. Estos eventos son sacados por la aplicación y provistos por el parseador en el orden en el cual ellos son leídos en la fuente del documento XML.
Muchos puede que aun tengan la necesidad de un ejemplo practico para tener una idea de donde utilizar StAX. Imaginen un documento XML con todos datos de los empleados de una gran organización de por ejemplo 5000 empleados, el trabajar con DOM implicaría cargar toda esa información en memoria y puede que el sistema no cuente con suficiente recursos para ello, mientras que trabajar con SAX implicaría parsear todo el documento, es aquí donde encaja StAX.
Una vez ya hemos dado algo de teoría, pasamos a la practica.
Dado un XML de empleados, mostrar únicamente aquellos donde el salario sea superior o igual a 30000.
Documento XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
<empleados> <empleado id="1"> <nombre>José Antonio</nombre> <apellido>Rodríguez</apellido> <salario>30000</salario> <cargo>programador</cargo> <direccion> <ciudad>Madrid</ciudad> <provincia>Madrid</provincia> <cp>28020</cp> <calle>alcala</calle> </direccion> </empleado> <empleado id="2"> <nombre>María José</nombre> <apellido>Rodríguez</apellido> <salario>35000</salario> <cargo>Contable</cargo> <direccion> <ciudad>Coslada</ciudad> <provincia>Madrid</provincia> <cp>28820</cp> <calle>henares</calle> </direccion> </empleado> <empleado id="3"> <nombre>María Isabel</nombre> <apellido>Rodríguez</apellido> <salario>35500</salario> <cargo>Contralor</cargo> <direccion> <ciudad>Torrejon de Ardoz</ciudad> <provincia>Madrid</provincia> <cp>28850</cp> <calle>Guadiana</calle> </direccion> </empleado> <empleado id="4"> <nombre>Fernando</nombre> <apellido>Carrillo</apellido> <salario>28000</salario> <cargo>gerente</cargo> <direccion> <ciudad>Madrid</ciudad> <provincia>Madrid</provincia> <cp>28029</cp> <calle>Ladera</calle> </direccion> </empleado> <empleado id="5"> <nombre>Claudia</nombre> <apellido>marquez</apellido> <salario>20000</salario> <cargo>Asistenta</cargo> <direccion> <ciudad>Madrid</ciudad> <provincia>Madrid</provincia> <cp>28002</cp> <calle>clara del rey</calle> </direccion> </empleado> </empleados> |
A continuación el código Java elaborado utilizando la Cursor API, asumiendo que estaríamos procesando un documento muy grande con la información de miles de empleados.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
package jaxp.stax; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.ArrayList; import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.events.XMLEvent; /** * Ejemplo elaborado con cursor API * @author @josedeveloper * */ public class StaxExample { private static final String TAG_SALARIO = "salario"; private static final String TAG_NOMBRE = "nombre"; public static <e> void main(String[] args) throws FileNotFoundException, XMLStreamException, FactoryConfigurationError { //Creamos el flujo XMLInputFactory xmlif = XMLInputFactory.newInstance(); //Cuando se crea una instancia de XMLStreamReader el evento inicial y actual es el START_DOCUMENT XMLStreamReader xmlsr = xmlif.createXMLStreamReader(new FileReader("PATH_FICHERO.xml")); ArrayList<string> nombres = new ArrayList<string>(); String tag = null; String nombre = null; String salario = null; int eventType; System.out.println("Iniciando el documento"); //iteramos con el cursor a lo largo del documento while (xmlsr.hasNext()){ //obtenemos el tipo de evento eventType = xmlsr.next(); //Al tener que manejar varios eventos el bloque switch resulta una solución elegante //para ir añadiendo case de eventos switch(eventType){ case XMLEvent.START_ELEMENT: //obtenemos la etiqueta tag = xmlsr.getLocalName(); if(tag.equals(TAG_NOMBRE)){ nombre = xmlsr.getElementText(); }else if(tag.equals(TAG_SALARIO)){ salario = xmlsr.getElementText(); if(Integer.parseInt(salario) >= 30000) nombres.add(nombre); } break; case XMLEvent.END_DOCUMENT: System.out.println("Fin del documento"); break; } } System.out.println("Empleados con salario mayor a 30000: "+nombres); } } |
la salida final sería la siguiente:
1 2 3 |
Iniciando el documento Fin del documento Empleados con salario mayor a 30000: [José Antonio, María José, María Isabel] |
Como han podido ver al realizar (o visualizar) el ejemplo, no resulta complejo utilizar StAX, lo complejo quizás pueda ser el entender como trabajan cada tipo de API y para eso nada mejor que la practica y por eso dejo de parte de ustedes realizar el ejemplo con la Iterator API.
Conclusión
El tratamiento (parsing) de documentos XML hoy en día resulta algo muy común, ya que el XML se esta convirtiendo o de facto ya lo es, el formato por defecto de intercambio de información, como en efecto podemos corroborarlo con los servicios web (tanto SOAP como REST) que establecen su comunicación mediante el envío y recepción de documentos XML, pero la realidad es que aun la cantidad de desarrolladores Java que desconocen o no utilizan StAX resulta muy grande, conviertiendolo en el gran desconocido, cuya consecuencia principal esta en la selección errónea en su lugar de DOM o SAX para el tratamiento del XML, cuando digo errónea no me refiero al estilo de programación sino a un mal uso de los recursos, sobretodo en esta época donde la conexión por medio de dispositivos móviles (moviles, pda’s, tablets, etc..) se ha incrementado a pasos agigantados y este es uno de los casos donde el uso de StAX viene como anillo al dedo, pero no resulta el único, ya que también dependiendo del caso (requerimientos y/o limitantes) su uso por ejemplo en un servidor puede resultar en una mejora en el rendimiento, sin que para esto se tenga que recurrir al aumento de recursos (mejor procesador, mas memoria RAM..) del equipo que efectúa el tratamiento del XML.
Información de este post ha sido obtenida del tutorial de Oracle y de jenkov.com