Comparación de las Tecnologías Java para XML

Ni la tecnología Java ni la tecnología XML necesitan ninguna introducción, ni tampo la sinergía entre ámbas "Código Portable y Datos Portables". Con el creciente interés en los servicios Web y las plataformas de comercio electrónico, XML se está uniendo a Java en la caja de herramientas de los desarrolladores. Hasta hoy, no menos de seis extensiones de la Plataforma Java potencian al desarrollador Java cuando construye aplicaciones basadas en XML:

  • Java API for XML Processing (JAXP)
  • Java API for XML/Java Binding (JAXB)
  • Long Term JavaBeans Persistence
  • Java API for XML Messaging (JAXM)
  • Java API for XML RPC (JAX RPC)
  • Java API for XML Registry (JAXR)

Esta página se dirige a la primera, el API Java para Procesar XML (JAXP). También se dirige a las tecnologías que JAXP proporciona directa o indirectamente al desarrollador Java, o las tecnologías que están relacionadas con él para poder porcesar documentos XML, entre otras:

  • SAX, Simple API for XML
  • DOM, Document Object Model API from W3C
  • XSLT, XML Style Sheet Language Transformations from W3C
  • XPath, XML Path Language from W3C
  • JDOM, "Java optimized" document object model API from jdom.org

Esta página está pensada para ofrecer una introducción a los diferentes APIs disponibles presentado algunos programas de ejemplo. Las diferencias de rendimiento se verán en la siguiente página, en la tercera página de este tutorial intentaremos ofrecer trucos sobre cómo mejorar el rendimiento de aplicaciones basadas en XML desde un punto de vista programático y arquitectural. Para poder comparar los programas de ejemplo, los hemos aplicado el mismo problema y hemos proporcionado una solución idéntica. El problema se ha mantenido sencillo para acomodar las diferentes capaciades de estas tecnologías. Los programas de ejemplo mostrados aquí podrían considerarse como micro-comparaciones. La demostración esencialmente se enfoca en el entendimiento de qué tecnologías se pueden aplicar para procesar documentos de entrada XML; no cubre en detalle la generación de documentos de salida XML.

Este tutorial no cubre XML y el procesamiento Java de XML en profundidad. El lector debe estar familiarizado tanto con XML como con el lenguaje de programación Java.

. Introducción a los Diferentes Modelos de Procesamiento XML

¿Qué significa para una aplicación estar basada en XML, o para entendernos, ser un Servicio Web? Con respecto a XML, principalmente significa que puede consumir documentos XML, aplicar su lógica de negocio o recuperar información y generar documentos XML resultantes. Estas tres fases pueden describirse en más detalle como:

  1. Procesamiento de entrada XML:
    • Analizar y validar el documento fuente.
    • Reconocer/buscar información importante basándonse en su localización o en su etiquetdo en el documento fuente.
    • Extraer la información importante una vez que se ha localizado.
    • Opcionalmente, mapear/unir la información recuperada a objetos de negocio.
  2. Manejo de lógica de negocio:
    • El procesamiento real de la información de entrada resultando opcionalmente en la generación de información de salida.
  3. Procesamiento de salida XML:
    • Construir un modelo de documento para generar con DOM, JDOM, etc.
    • Aplicar hojas de estilo SXLT o serializar directamente a XML

SAX y DOM son los modelos de procesamiento más comunes. Para usar SAX para procesar un documento XML, tenemos que codificar métodos para manejar eventos lanzados por el analizador según encuentra diferentes tokens del lenguaje de marcas. Con DOM, tenemos que escribir código para pasar a través de una estructura de datos tipo árbol creada por el analizador desde el documento fuente. Como un analizador SAX genera un flujo temporal de eventos, se deben hacer en un sólo ciclo los cuatro paso de procesamiento de entrada XML descritos arriba (nombrado, análisis, reconocimiento, extracción y mapeo): cada evento capturado es manejado inmediatamente y la información importante es pasada junto con el evento. Cuando usamos DOM, el procesamiento de la entrada XML se hace al menos en dos ciclos: primero, el analizar DOM crea una estructura de datos tipo árbol que modela el documento fuente XML (árbol DOM), luego pasamos a través del árbol DOM, buscando información relevante para extraerla y procesarla posteriormene; este último ciclo se puede repetir tantas veces como sea necesario mientras el árbol DOM exista en memoria.

Tabla 1: Caracterísiticas SAX y DOM

SAX DOM
Modelo basado en eventos Estructura de datos tipo árbol
Acceso serie (flujo de eventos) Acceso aleatorio (estructura de datos en memoria
Bajo uso de memoria (sólo se generan eventos) Alto uso de memoria (todo el documento se carga en memoria
Para procesar partes del documento (capturar eventos importantes) Para editar el documento (procesar la estructura de datos en memoria)
Para procesar el documento sólo una vez (flujo de eventos temporal). Para procesar el documento múltiples veces (documento cargado en memoria).

XSLT es modelo de procesamiento XML de nivel muy superior a SAX y DOM. XSLT requiere que el desarrollador codifique reglas (plantillas) que serán aplicadas cuando se encuentren los patrones especificados en el documento fuente. Estos patrones se especifican usando el lenguaje Xpath. Xpath se usa para localizar y extraer información desde el documento fuente y está especialmente dirigido a los pasos 1.b y 1.c del procesamiento de XML detallado arriba. Mientras que SAX y DOM requieren que el desarrollador Java escriba código Java, XSLT (a parte del propio motor de invocación) sólo requiere escribir hojas de estilo que son ellas mismas documentos XML. Comparado con la programación DOM y SAX, la progrmación XSLT podría verse como un Script.

Tabla 2: Fases de procesamiento SAX, DOM y XSLT

Fase de Procesamiento SAX DOM XSLT

 

Procesamiento de entrada XML

 

Analizar y validar Interno Interno o basado en SAX Basado en SAX o DOM
Reconocer/buscar Capturar eventos con manejadores de eventos Buscar en el árbol con buscadores Patrones Xpath
Extraer Capturar eventos Obtener valores de atributos, contenidos de nodos: métodos del API Obtener valores de atributos, contenidos de nodos: sentencias Xpath
Mapear/Unir Crear objetos de negocio desde la información extraída Crear objetos de negocio desde la información extraída Si lo hay, a través de DOM o SAX (tuberías)

 

Procesamiento de salida XML

 

Construcción No hay soporte por defecto, pero se puede hacer generando una secuencia de llamadas a métodos manejadores de eventos apropiadamente balanceada Parte implícita del modelo: API de métodos factoría Parte implícita del modelo: sentencias XSL.
Serialización No hay soporte por defecto, pero puede hacerse con manejadores de eventos personalizados. Soprote de implementación específico, o a través de transformaciones de identidades XSLT. Parte implícita del modelo: metodos de sentencias de salida XSL.

Algunos de los APIs Java disponibles para procesar XML (es decir DOM, XSLT) podrían estar construidos encima de otros, añadir más niveles de abstracción, y por hende más potencia, pero también se podrían solapar dejando al desarrollador la elección de cuándo utilizar uno y cuando otro. El dibujo de abajo muestra las dependencias entre estas tecnologías así como algunas posibilidades (representadas por flechas mono o bi-direccionales) ofrecidas al desarrollador que necesita implementar una aplicación basada en XML:

Ilustración 1:
Una aplicación podría generar/procesar documentos XML desde/hacia objetos de negocio, usando SAX, DOM, XPath o XSLT; una aplicación podría incluso algunas veces usar un modelo de documento como JDOM para representar las estructuras de datos principales y aplicarles la lógica de neogocio.

Para todas estas tecnologías diferentes, SAX, DOM, XSLT, XPath y JDOM, hemos implementado programas de ejemplo pensadas para comparar los diferentes APIs que están siendo usados desde los puntos de vista programático (capacidades, facilidad de uso) y de rendimiento. Primero, presentaremos la aplicación de ejemplo dominio, luego presentaremos cada API y describiremos el correspondiente programa de ejemplo.

. Aplicación de Ejemplo Dominio

Los programas de ejemplo que se presentarán en este tutorial están basados en diferentes APIs de procesamiento aplicados al mismo conjunto de documentos y proporcionan la misma salida. Los documentos XML procesados usan estas diferentes técnicas conforme a la misma DTD Document Type Definition o esquema XML. Estos esquemas especifican la representación de un tablero de ajedrez. Para poder comparar posteriormente estos programas de ejemplo, hemos aumentado el tamaño de los documentos procesados (para aumentar la carga de trabajo); los esquemas se ha extendido de forma coherente para describir conjuntos de dichas configuraciones de tablero de ajedrez (desde 10 hasta 5000).

Ilustración 2: Una Configuración de Tablero de Ajedrez

Cada programa procesa un conjunto de configuraciones de tableros de ajedrez sacando la misma configuración en un sencillo formato de texto leíble por humanos. Las diferentes implementaciones basadas en SAX, DOM, XSLT y XPath cuando se aplican a los mismos documentos de entrada proporcionan la misma salida.

Abajo tenemos dos representaciones de la misma configuración del tablero de ajedrez, una está en XML y la otra está en texto normal. La segunda ha sido generada a partir de la primera usando uno de los programas de ejemplo:

Código de Ejemplo 1: Una representación XML de una configuración tablero de Ajedrez:

<CHESSBOARD>
 <WHITEPIECES>
  <KING><POSITION COLUMN="G" ROW="1"/></KING>
  <BISHOP><POSITION COLUMN="D" ROW="6"/></BISHOP>
  <ROOK><POSITION COLUMN="E" ROW="1"/></ROOK>
  <PAWN><POSITION COLUMN="A" ROW="4"/></PAWN>
  <PAWN><POSITION COLUMN="B" ROW="3"/></PAWN>
  <PAWN><POSITION COLUMN="C" ROW="2"/></PAWN>
  <PAWN><POSITION COLUMN="F" ROW="2"/></PAWN>
  <PAWN><POSITION COLUMN="G" ROW="2"/></PAWN>
  <PAWN><POSITION COLUMN="H" ROW="5"/></PAWN>
 </WHITEPIECES>
 <BLACKPIECES>
  <KING><POSITION COLUMN="B" ROW="6"/></KING>
  <QUEEN><POSITION COLUMN="A" ROW="7"/></QUEEN>
  <PAWN><POSITION COLUMN="A" ROW="5"/></PAWN>
  <PAWN><POSITION COLUMN="D" ROW="4"/></PAWN>
 </BLACKPIECES>
</CHESSBOARD>

Código de ejemplo 2: Una representación en formato de texto de una configuración de tablero de ajedrez:

White king: G1
White bishop: D6
White rook: E1
White pawn: A4
White pawn: B3
White pawn: C2
White pawn: F2
White pawn: G2
White pawn: H5
Black king: B6
Black queen: A7
Black pawn: A5
Black pawn: D4

. Documentos XML procesados

Se han producido dos conjuntos de documentos de entrada XML:

  • Un conjunto de documentos XML conformes a una Document Type Definition
  • Un conjunto de documentos XML conformes a un esquema XML equivalente.

Como hay muy pocos analizadores XML que soporten la especificación XML Schema, la mayoría de los programas de ejemplo usan el primer conjunto de documentos XML, basados en DTD. El segundo conjunto de documentos sólo se usa para una comparación de los respectivos documentos entre la validación DTD y con esquema XML.

. Documentos Basados en DTD

Dos DTDs especifican el formato de los documentos XML que son usados como entradas en los programas de ejemplo:

  • Una DTD que especifica una simple configuración de tablero de ajedrez.
  • Una DTD relacionado con el anterior para especificar un conjunto de configuraciones de tablero de ajedrez.

Código de ejemplo 3: El DTD para una configuración de tablero de ajedrez, (dtd/Chessboard.dtd)

<!ELEMENT CHESSBOARD (WHITEPIECES, BLACKPIECES)>
<!ENTITY % pieces
  "KING,
   QUEEN?,
   BISHOP?, BISHOP?,
   ROOK?, ROOK?,
   KNIGHT?, KNIGHT?, 
   PAWN?, PAWN?, PAWN?, PAWN?,
   PAWN?, PAWN?, PAWN?, PAWN?"
>
<!ELEMENT WHITEPIECES (%pieces;)>
<!ELEMENT BLACKPIECES (%pieces;)>
<!ELEMENT POSITION EMPTY>
<!ATTLIST POSITION
  COLUMN (A|B|C|D|E|F|G|H) #REQUIRED
  ROW (1|2|3|4|5|6|7|8) #REQUIRED
>
 
<!ELEMENT KING (POSITION)>
<!ELEMENT QUEEN (POSITION)>
<!ELEMENT BISHOP (POSITION)>
<!ELEMENT ROOK (POSITION)>
<!ELEMENT KNIGHT (POSITION)>
<!ELEMENT PAWN (POSITION)>

Este esquema fuerza varias restricciones desde el dominio de la aplicación:

  • Sólo un rey por cada color puede estar presente en un momento dado en tablero de ajedrez.
  • Cero o una reína por cada color.
  • De cero a dos alfiles por cada color.
  • De cero a dos caballos por cada color.
  • De cero a dos torres por cada color.
  • De cero a ocho peones por cada color.
  • Una pieza debe estar en una de las columnas A, B, C, D, E, F, G y H
  • Una pieza debe estar en una de las filas 1, 2, 3, 4, 5, 6, 7 y 8

A pesar de todos, este esquema no evita que dos piezas compartan la misma posición exacta.

El siguiente DTD usa el anterior para especificar un conjunto de configuraciones de tablero de ajedrez que serán hijos de un sólo elemento CHESSBOARDS.

Código de ejemplo 4: El DTD para múltiples configuraciones de tableros de ajadrez: (dtd/Chessboards.dt)

<!ELEMENT CHESSBOARDS (CHESSBOARD*)>
<!ENTITY % chessboard SYSTEM "Chessboard.dtd">
%chessboard;

El número de configuraciones de tableros de ajedrez es ilimitado, permitiendo que cualquier número de configuraciones sean definidas en un sólo documento. Para poder comparar los distintos programas, se han creado documentos con 10, 100, 200, 300, 400, 500, 1000, 2000, 3000, 4000 y 5000 configuraciones.

Código de ejemplo 5: Un documento XML conforme a la DTD (Chessboards-[10-5000].xml)

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

<!DOCTYPE CHESSBOARDS SYSTEM "dtd/Chessboards.dtd">

<CHESSBOARDS>
 <CHESSBOARD>
  <WHITEPIECES>
   <KING><POSITION COLUMN="G" ROW="1" /></KING>
   <BISHOP><POSITION COLUMN="D" ROW="6" /></BISHOP>
   <ROOK><POSITION COLUMN="E" ROW="1" /></ROOK>
   <PAWN><POSITION COLUMN="A" ROW="4" /></PAWN>
   <PAWN><POSITION COLUMN="B" ROW="3" /></PAWN>
   <PAWN><POSITION COLUMN="C" ROW="2" /></PAWN>
   <PAWN><POSITION COLUMN="F" ROW="2" /></PAWN>
   <PAWN><POSITION COLUMN="G" ROW="2" /></PAWN>
   <PAWN><POSITION COLUMN="H" ROW="5" /></PAWN>
  </WHITEPIECES>
  <BLACKPIECES>
   <KING><POSITION COLUMN="B" ROW="6" /></KING>
   <QUEEN><POSITION COLUMN="A" ROW="7" /></QUEEN>
   <PAWN><POSITION COLUMN="A" ROW="5" /></PAWN>
   <PAWN><POSITION COLUMN="D" ROW="4" /></PAWN>
  </BLACKPIECES>
 </CHESSBOARD>
 <CHESSBOARD>
  ...
 </CHESSBOARD>
</CHESSBOARDS>

. Documentos Basados en Esquema XML

De forma similar a los DTDs presentados arriba, dos esquemas XML especifican el formato de los documentos XML que se usan como entrada para la comparación de validaciones entre DTD y Esquema XML:

  • Un Esquema XML especificando una sóla configuración de tablero de ajedrez.
  • Un Esquema XML relacionado con el anterior para especificar un conjunto de configuracioens de tablero de ajedrez.

Código de ejemplo 6: El Esquema XML para una configuración de tablero de ajerdrez: (xsd/Chessboard.xsd)

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

<xsd:schema
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://mde.sun.com/Chessboard"
  xmlns="http://mde.sun.com/Chessboard"
  elementFormDefault="qualified">

 <xsd:element name="CHESSBOARD">
  <xsd:complexType>
   <xsd:sequence>
    <xsd:element name="WHITEPIECES" type="pieces" />
    <xsd:element name="BLACKPIECES" type="pieces" />
   </xsd:sequence>
  </xsd:complexType>
 </xsd:element>
  
 <xsd:complexType name="pieces">
  <xsd:sequence>
   <xsd:element name="KING" type="piece"
     minOccurs='1' maxOccurs='1'/>
   <xsd:element name="QUEEN" type="piece"
     minOccurs='0' maxOccurs='1'/>
   <xsd:element name="BISHOP" type="piece"
     minOccurs='0' maxOccurs='2'/>
   <xsd:element name="ROOK" type="piece"
     minOccurs='0' maxOccurs='2'/>
   <xsd:element name="KNIGHT" type="piece"
     minOccurs='0' maxOccurs='2'/>
   <xsd:element name="PAWN" type="piece"
     minOccurs='0' maxOccurs='8'/>
  </xsd:sequence>
 </xsd:complexType>
  
 <xsd:complexType name="piece">
  <xsd:sequence>
   <xsd:element name="POSITION"
     minOccurs='1' maxOccurs='1'>
    <xsd:complexType>
     <xsd:attribute name="COLUMN" use='required'>
<xsd:simpleType>
 <xsd:restriction base="xsd:string">
  <xsd:pattern value="[A-H]"/>
 </xsd:restriction>
</xsd:simpleType>
     </xsd:attribute>
     <xsd:attribute name="ROW" use='required'>
<xsd:simpleType>
 <xsd:restriction base="xsd:positiveInteger">
  <xsd:minInclusive value="1"/>
  <xsd:maxInclusive value="8"/>
 </xsd:restriction>
</xsd:simpleType>
     </xsd:attribute>
    </xsd:complexType>
   </xsd:element>
  </xsd:sequence>
 </xsd:complexType>
</xsd:schema>

Este esquema fuerza las mismas restricciones del dominio de aplicación que el DTD, pero usa un rango d epatrones como "minOccurs='0' maxOccurs='8'" y "value="[A-H]".

Código de ejemplo 7: El Esquema XML para múltiples configuraciones de tableros de ajedrez: (xsd/Chessboards.xsd)

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

<xsd:schema 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://mde.sun.com/Chessboards"
  xmlns="http://mde.sun.com/Chessboards"
  xmlns:cb="http://mde.sun.com/Chessboard">

 <xsd:import namespace="http://mde.sun.com/Chessboard" 
   schemaLocation='Chessboard.xsd' />

 <xsd:element name="CHESSBOARDS">
  <xsd:complexType>
   <xsd:sequence>
    <xsd:element ref="cb:CHESSBOARD" 
maxOccurs='unbounded'/>
   </xsd:sequence>
  </xsd:complexType>
 </xsd:element>   
</xsd:schema>

Los documentos XML conformes a Chessboards.dtd y Chessboards.xsd tienen una estructura y contenidos indénticos, la única excepción es la substitución del Document Type Declaration por una referencia al Esquema XML.

Para las comparaciones que implican esquemas XML, se utilizó un documento con 100 configuraciones de tablero de ajedrez.

Código de ejemplo 8: El documento XML conforme al esquema XML (Chessboards-schema-100.xml)

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

<cbs:CHESSBOARDS 
  xmlns:cbs="http://mde.sun.com/Chessboards"
  xmlns="http://mde.sun.com/Chessboard"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation='http://mde.sun.com/Chessboard 
    xsd/Chessboard.xsd
    http://mde.sun.com/Chessboards 
    xsd/Chessboards.xsd'>
 <CHESSBOARD>
  <WHITEPIECES>
   <KING><POSITION COLUMN="G" ROW="1" /></KING>
   <BISHOP><POSITION COLUMN="D" ROW="6" /></BISHOP>
   <ROOK><POSITION COLUMN="E" ROW="1" /></ROOK>
   <PAWN><POSITION COLUMN="A" ROW="4" /></PAWN>
   <PAWN><POSITION COLUMN="B" ROW="3" /></PAWN>
   <PAWN><POSITION COLUMN="C" ROW="2" /></PAWN>
   <PAWN><POSITION COLUMN="F" ROW="2" /></PAWN>
   <PAWN><POSITION COLUMN="G" ROW="2" /></PAWN>
   <PAWN><POSITION COLUMN="H" ROW="5" /></PAWN>
  </WHITEPIECES>
  <BLACKPIECES>
   <KING><POSITION COLUMN="B" ROW="6" /></KING>
   <QUEEN><POSITION COLUMN="A" ROW="7" /></QUEEN>
   <PAWN><POSITION COLUMN="A" ROW="5" /></PAWN>
   <PAWN><POSITION COLUMN="D" ROW="4" /></PAWN>
  </BLACKPIECES>
 </CHESSBOARD>
 <CHESSBOARD>
  ...
 </CHESSBOARD>
</cbs:CHESSBOARDS>

. Programas de Ejemplo

Todos los programas presentados en este tutoral usan el API Java para Procesar XML (JAXP) para hacer de interface entre las diferentes implementaciones subyacentes del analizador SAX, el constructor de documentos DOM y el motor de Transformación XSL.

. Java API for XML Processing (JAXP)

El API Java para Procesamiento XML (JAXP) permite a las aplicaciones analizar y transformar documentos XML usando un API que es independiente de cualquier implementación de procesador XML. A través de un esquema conectable, los desarrolladores podrían cambiar las implementaciones del procesador XML sin impactar en sus aplicaciones. JAXP 1.1 soporta los siguientes estándards:

  • SAX versión 2.0
  • DOM nivel 2
  • XSLT 1.0

JAXP fue usado para crear e invocar a diferentes implementaciones de analizadores XML y motores XSLT. Para la comparación de un API particular (SAX, DOM, XSLT), se utilizó el mismo programa, sólo se cambió el analizador XML o el motor XSLT subyacentes.

El API trata sobre el patrón de diseño factoría para crear un nuevo analizador SAX, un constructor de documentos DOM o motores de hojas de estilo. Abajo tenemos ejemplos típicos del uso del API para procesar un documento XML usando respectivamente SAX, DOM y XSLT.

Cuando usamos el API SAX a través de JAXP, debemos:

  • Crear una nueva factoría de analizadores SAX.
  • Configurar la factoría.
  • Crear un nuevo analizador desde la factoría.
  • Seleccionar el manejador de documento del analizador, el manejador de error, el manejador de DTD y el resolvedor de entidades.
  • Analizar el/los documento(s) XML.

Código de ejemplo 9: Invocar al analizador SAX usando JAXP y analizar el documento como un stream de eventos SAX:

import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;

boolean validating;
String fileToProcess;
...
SAXParserFactory factory 
  = SAXParserFactory.newInstance();
factory.setValidating(validating);
SAXParser parser = factory.newSAXParser();
...
parser.parse(fileToProcess, new HandlerBase() {
 ... // Custom implementation of the HandlerBase 
     // to process the document as SAX events
});
...

Los pasos títpicos cuando se usa DOM a través de JAXP son:

  • Crear una nueva factoría de constructores de documentos DOM.
  • Configurar la Factoría.
  • Crear un nuevo constructor de documentos desde la factoría.
  • Seleccionar el manejador de error del analizador subsyacente y el resolvedor de entidades.
  • Analizar el/los documento(s) XML para generar un árbol DOM.

Código de ejemplo 10: Invocar a un constructor de documentos usando JAXP, analizar y procesar el documento como un árbol DOM:

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

boolean validating;
String fileToProcess;
...
DocumentBuilderFactory factory 
  = DocumentBuilderFactory.newInstance();
factory.setValidating(validating);
DocumentBuilder builder
  = factory.newDocumentBuilder();
builder.setErrorHandler(new ErrorHandler() {
 ...   
});
...
Document document = builder.parse(fileToProcess);
... // Processing the document as a DOM tree

Cuando se usa JAXP para realizar transformaciones XSL, los pasos a seguir no son muy diferentes de los de SAX o DOM:

  • Crear una nueva factoría de transformadores.
  • Configurar la Factoría.
  • Crear un nuevo transformador desde la factoría con una hoja de estilo particular.
  • Seleccionar el oyente de error y el resolvedor de URI.
  • Aplicar la hoja de estilos a el/los documento(s) XML para generar árboles DOM, eventos SAX o escribir la salida en un stream.

Código de ejemplo 11: Invocar a un motor XSLT usando JAXP y procesar el documento con una hoja de estilo XSLT; el API permite pasar parámetros a los motores de hoja de estilo:

import javax.xml.transform.*;

String styleSheetFile;
String fileToProcess;
OutputStream out;
Properties properties;
...
TransformerFactory factory 
  = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(
  new SAXSource(new InputSource(styleSheetFile)));
for (Enumeration i = properties.propertyNames();
     i.hasMoreElements();) {
 String name = (String) i.nextElement();
 transformer.setParameter(name,
   "\'" + properties.getProperty(name) + "\'");
}
transformer.transform(
  new SAXSource(new InputSource(fileToProcess)),
  new StreamResult(out));
...

. Estructura Común de los Programas de Ejemplo

Todos los programas de ejemplo comparten una estructura común que posteriormente nos permitirá hacer una comparación. Todos siguen los pasos típicos de la utilización de JAXP presentados arriba, y adicionalmente incluyen dos bucles para procesar el mismo documento varias veces y en varias ejecuciones. Por cada ejecución, se usa una factoría para crear un analizador o un procesador de hojas de estilo que a su vez es usada para procesar un documento fuente XML varias veces. La validación del documento fuente contra sus DTDs o Esquemas XML declarados se implementa configurando la factoría a través de su método setValidating que crea un analizador con o sin validación.

Código de ejemplo 12: Ejemplo de la estructura de los programas de ejemplo: (ChessboardSAXPrinter.java)

import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;

public class ChessboardSAXPrinter {
 private SAXParser parser;

 public ChessboardSAXPrinter(boolean validating)
   throws Exception {
  SAXParserFactory factory 
    = SAXParserFactory.newInstance();
  factory.setValidating(validating);
  parser = factory.newSAXParser();
  ...
  return;
 }

 public void print(String fileName, PrintStream out)
   throws SAXException, IOException {
  ...
  parser.parse(fileName, ...);
  return;
 }
  
 public static void main(String[] args) {
  ...   
  for (int k = 0; k < r; k++) {
    // r: number of runs
   ChessboardSAXPrinter saxPrinter
     = new ChessboardSAXPrinter(validating);
   long time = System.currentTimeMillis();
   for (int i = 0; i < n; i++) {
     // n: number of document processed per run
    saxPrinter.print(args[0], out);
   }
   // print out the average time (s) 
   // to process a document during the current run
   System.err.print( 
     (((double) (System.currentTimeMillis()
     - time)) / 1000 / n) + "\t");
  }
  ...
 }
}

. Programa de Ejemplo SAX

El API SAX (Simple API for XML) usa un modelo basado en eventos y permite el procesamiento de un documento fuente como un stream de eventos. Los eventos son disparados mientras se analiza como un flujo continuo de retrollamadas e invocaciones a métodos. Los eventos están anidados de la misma forma que los elementos en el documento, por lo tanto, no se crea ningún modelo de documento intermedio. Como el uso de memoria es bajo, el modelo de programación puede ser complejo especialmente si la estructura no corresponde con la estructura de datos de la aplicación. Como genera un flujo temporal de eventos, el API SAX no puede utilizarse cuando un modelo de documento tiene que ser editado o procesado varias veces.

El API SAX define varios interfaces (alguno de los interfaces de SAX 1.0 fueron renombrados en SAX 2.0):

  • org.xml.sax.Parser (XMLReader en SAX 2.0) interfaces para analizadores SAX:
    • Analiza un documento XML.
    • Permite a una aplicación registrar:
      • Un manejador de eventos de documento.
      • Un manejador de error.
      • Un manejador de DTD.
      • Un resolvedor de entidades.
  • org.xml.sax.DocumentHandler (ContentHandler en SAX 2.0) interface para recibir eventos de documento, notificación de:
    • El inicio o final de un documento.
    • El inicio y final de un elemento.
    • Datos de caracter.
    • Espacios en blanco ignorables en el contenido de elementos.
    • Instrucciones de procesamiento.
  • org.xml.sax.ErrorHandler interface para recibir eventos de error SAX, notificación de:
    • Un error recuperable.
    • Un error fatal/no recuperabe.
    • Un aviso.
  • org.xml.sax.DTDHandler interface para recibir nitificación de eventos básicos relacionados con DTD, notificación de:
    • Un evento de declaración de notación.
    • Un evento de declaración de entidad sin analizar.
  • org.xml.sax.EntityResolver interface para resolver referencias a entidades externas.
  • org.xml.sax.HandlerBase (DefaultHandler en SAX 2.0) implementación por defecto de los cuatro interfaces anteriores.

Una aplicación debe proporcionar al menos un manejador de documento (o contenido) para poder capturar los eventos relevantes y procesarlos.

Ilustración 3: Cuando se usa el API SAX, como mínimo un desarrollador tiene que implementar un DocumentHandler (ContentHandler en SAX 2.0) o subclasificar BaseHandler (DefaultHandler) para que se puedan capturar los eventos importantes y, opcionalmente los objetos de negocio mapeados o directamente manejados por la lógica de negocio.

El sencillo programa presentado abajo implementa el interface HandlerBase, y especialmente el método startElement. Se usa una SAXParserFactory para crear un nuevo SAXParser. La implementación personalizada del interface HandlerBase y el path del documento fuente XML a procesar son pasados al analizador. Durante el análisis, se llama al método startElement por cada etiqueta de inicio del documento fuente.

Código de ejemplo 13: El programa procesa un documento XML basándose en el API SAX (ChessboardSAXPrinter.java); el método startElement imprime información basada en las etiquetas de inicio que captura:

import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;

public class ChessboardSAXPrinter {
 private SAXParser parser;
 private PrintStream out;

 public class ChessboardHandler extends HandlerBase {
  private boolean whitePiece = false;
  
  public void startElement(String name,
     AttributeList attrs) {
   if (name.equals("WHITEPIECES")) {
    whitePiece = true;
   } else if (name.equals("BLACKPIECES")) {
    whitePiece = false;
   } else if (name.equals("KING")
  || name.equals("QUEEN")
  || name.equals("BISHOP")
  || name.equals("ROOK")
  || name.equals("KNIGHT")
  || name.equals("PAWN")) {
    out.print((whitePiece ? "White" : "Black")
  + " "+ name.toLowerCase() + ": ");
   } else if (name.equals("POSITION")) {
    if (attrs != null) {
     out.print(attrs.getValue("COLUMN"));
     out.println(attrs.getValue("ROW"));
    }
   }
   return;
  }
  ...
 }
 ...
}

Durante el análisis, el método startElement captura los sigueintes eventos de etiquetas de inicio:

  1. BLACKPIECES y WHITEPIECES para seguir el color de las piezas anidadas.
  2. KING, QUEEN, BISHOP, ROOK, KNIGHT, PAWN para imprimir el nombre de la pieza y su color.
  3. POSITION para imprimir la posición de la pieza, dando el atributo de elemento ROW y COLUMN.

Los otros eventos no son capturados, pero una aplicación del mundo real podría requerir que se capturaran eventos como endElement, characters (que notifica un contenido textual) y mantener un contexto más complejo para mapear el stream de eventos dentro de objetos de negocio sobre los que poder aplicar más tarde la lógica de negocio. Usando SAX podría ser tedioso, pero sería la técnica más rápida.

Mientras no sea una obligación el API SAX podría ser usado por constructores de documentos DOM para construir un árbol DOM desde un documento fuente XML.

. Programa de Ejemplo DOM

DOM (Document Object Model) es una especificación W3C presentada como "un interface neutral del lenguaje y la plataforma que permitirá a los programas y scripts acceder dirnámicamente y actualizar el contenido, la estructura y el estilo de documento." Esencialmente es una estructura de datos en forma de árbol y un conjunto de métodos para acceder y editar esa estructura. Como es una estructura de datos en-memoria, el uso de memoria es mucho más alto que para SAX, pero el modelo de documento puede accederse aleatoriamente y puede ser procesado múltiples veces.

El API DOM define interfaces para cada una de las entidades de un documento XML:

  • Interface org.w3c.dom.Node: un sólo nodo en el árbol del documento.
    • define métodos para acceder, insertar, eliminar y reemplazar nodos hijo.
    • Define métodos para acceder al nodo padre.
    • Define métodos para acceder al documento.
  • Inteface org.w3c.dom.Document es un Node que representa un documento completo XML.
  • Interface org.w3c.dom.Text es un Node que representa el contenido textual de un elemento XML.

La aplicación podría aplicar su lógica de negocio directamente al árbol DOM, o ir primero a través de un estado tradicional de mapear la información relevante desde el árbol DOM en objetos de negocio:

Ilustración 4: Cuando se usa el API DOM, la aplicación tiene que acceder o editar una representación en-memoria del documento fuente.

El programa presentado abajo usa el API DOM para analizar y cagar en memoria un documento XML describiendo un conjunto de configuraciones de tablero de ajedrez. Pasa a través del árbol DOM resultante y saca las mismas configuracioens en formato de texto.

Se usan dos implementaciones diferentes para iluminar las diferencias potenciales en rendimiento cuando se usan diferentes métodos del API DOM: acceder a los elementos por sus nombres o en relación a sus padres:

Código de ejemplo 14: El programa de procesamiento XML basado en el API DOM (ChessboardDOMPrinter.java), el método print baja por el árbol accediendo a los elementos en relación a sus nodos padre:

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

public class ChessboardDOMPrinter {
 private DocumentBuilder builder;

 public void print(String fileName, PrintStream out)
   throws SAXException, IOException {
  Document document = builder.parse(fileName);
  NodeList nodes_i 
    = document.getDocumentElement().getChildNodes();
  for (int i = 0; i < nodes_i.getLength(); i++) {
   Node node_i = nodes_i.item(i);
   if (node_i.getNodeType() == Node.ELEMENT_NODE
 && ((Element) node_i).getTagName()
    .equals("CHESSBOARD")) {
    Element chessboard = (Element) node_i;
    NodeList nodes_j = chessboard.getChildNodes();
    for (int j = 0; j < nodes_j.getLength(); j++) {
     Node node_j = nodes_j.item(j);
     if (node_j.getNodeType() == Node.ELEMENT_NODE) {
Element pieces = (Element) node_j;
NodeList nodes_k = pieces.getChildNodes();
for (int k = 0; k < nodes_k.getLength); k++) {
 Node node_k = nodes_k.item(k);
 if (node_k.getNodeType() == Node.ELEMENT_NODE) {
  Element piece = (Element) node_k;
  Element position 
    = (Element) piece.getChildNodes().item(0);
  out.println((pieces.getTagName()
     .equals("WHITEPIECES")
   ? "White " : "Black ")
  + piece.getTagName().toLowerCase()
  + ": "
  + position.getAttribute("COLUMN")
  + position.getAttribute("ROW"));
 }
}
     }
    }
   }
  }
  return;
 }
}

Este programa baja por el árbol DOM generado por el constructor de documento desde el documento de entrada XML y:

  1. Obtiene todos los elementos CHESSBOARD.
  2. Por cada elemento CHESSBOARD obtiene los subelementos BLACKPIECES y WHITEPIECES.
  3. Por cada uno de los elementos BLACKPIECES y WHITEPIECES, obtiene los subelementos KING, QUEEN, BISHOP,ROOK, KNIGHT y PAWN.
  4. Por cada uuno de los elementos KING, QUEEN,BISHOP, ROOK, KNIGHT y PAWN imprime el color, el nombre y la posición especificada por los atributos ROW y COLUMN.

La siguiente implementación alternativa no difiere en el algoritmo pero los recupera por el nombre. Aunque parece más elegante podría ser menos efectiva ya que este método busca los elementos en todo el subárbol, no sólo en el siguiente nivel. Globalmente, en programas simples, DOM parece más complicado que SAX. Realmente, esta última implementación podria hacerse más sencilla. Como el método getElementsByTagName recupera todos los hijos y nietos dando un nombre especificado, podría recolectar todos los elementos POSITION empezando por la raíz del docmento y luego por cada elemento devuelto, recuperar el nombre de la pieza, (el nombre de la etiqueta del padre), y el color (basado en el nombre de la etiqueta del abuelo).

Código de ejemplo 15: Una implementación "nativa" del método print basada en el API DOM que accede a elementos por el nombre en vez por su posición relativa en el árbol (ChessboardDOMPrinter.java).

public void print(String fileName, PrintStream out)
  throws SAXException, IOException {
 Document document = builder.parse(fileName);
 NodeList positions 
   = document.getElementsByTagName("POSITION");
 for (int i = 0; i < positions.getLength(); i++) {
  Element position = (Element) positions.item(i);
  Element piece = (Element) position.getParentNode();
  Element pieces = (Element) piece.getParentNode();
  out.println(
    (pieces.getTagName().equals("WHITEPIECES")
     ? "White " : "Black ")
    + piece.getTagName().toLowerCase() + ": "
    + position.getAttribute("COLUMN")
    + position.getAttribute("ROW"));
 }
 return;
}

. Programa de Ejemplo XSLT

XSL Transformations es un lenguaje para describir cómo transformar un documento XML (explícita o implícitamene representado como un árbol) en otro; XSLT es un árbol para transformaciones de árboles, desde un árbol fuente a un árbol resultante. Permite definir plantillas (reglas) que serán aplicadas sobre los elementos del documento fuente e insertar elementos en el árbol resultante. El documento resultante puede ser otro documento XML bien formateado (XML, WML), un documento HTML, un documento de texto, o cualquier otro formato para el que este disponible el método de salida apropiado. XSLT usa expresiones XPath para consultar elementos desde el árbol fuente o para evaluar fragmentos del documento a ser insertados dentro del árbol resultante.

Ilustración 5: XSL Transformations, transforma un documento fuente XML en otro documento que puede ser de cualquier formato, XML, HTML, etc, aplicando una hoja de estilo.

Un procesador XSLT lee un documento fuente XML y una hoja de estilo XSL. La hoja de estilo es a su vez un documento XML bien formateado. Dependiendo de la implementación, un motor XSLT podría leer una fuente de entrada como eventos SAX o árboles DOM y también generar eventos SAX o árboles DOM.

Este progama usa un motor XSLT y una hoja de estilo para transformar un documento XML que describe un conjunto de configuraciones de tableros de ajedrez en sus correspondientes formatos de texto. Se usa una TransformerFactory para crear un nuevo Transformer, entonces la hoja de estilo y el Transformer se usan ara procesar el documento fuente generado.

El motor XSLT aplica la siguiente hoja de estilo a cada documento de entrada:

Código de ejemplo 16: La hoja de estilo para transformar documentos XML que representan configuraciones de tableros de ajedrez (ChessboardPrinter.xsl)

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

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

 <xsl:strip-space elements="*" />

 <xsl:output method="text"/> 

 <xsl:template match="/">
  <xsl:apply-templates />
 </xsl:template> 

 <xsl:template match="WHITEPIECES/*">
  <xsl:value-of select="concat('White ', name(),
    ': ', [email protected], [email protected])" />
  <xsl:text>
</xsl:text>
 </xsl:template> 

 <xsl:template match="BLACKPIECES/*">
  <xsl:value-of select="concat('Black ', name(),
    ': ', [email protected], [email protected])" />
  <xsl:text>
</xsl:text>
 </xsl:template>

</xsl:stylesheet>

Esta hoja de estilo es bastante simple, define dos plantillas, una que corresponde con las piezas blancas (pattern"WHITEPIECES/*") y otra que corresponde con las piezas negras (pattern"BLACKPIECES/*"). Cuando se aplica una de estas plantilla, inserta en el árbol resultante un nodo de texto conteniendo el string que describe el color, el nombre y la posición de la pieza corresponidente. Cuando una plantilla no se aplica nunca más, el árbol resultante se imprime usando el método de salida de texto.

Ilustración 6: XSLT puede ser usada para procesar o post-procesar documentos XML antes o después de que sean manejados por la lógica de negocios de la aplicación.

. Programa de Ejemplo XPath

Algunos motores XSLT (como Xalan deApache.org) permiten invocar su propia implementación de XPath independientemente a través de un API específico. Una aplicación podría usar directamente Xpath para consultar la información desde un documento fuente XML o para evaluar expresiones contra el documento fuente.

El siguiente programa usa el API DOM para analizar y cargar en memoria un documento XML que describe un conjunto de configuraciones de tableros de ajedrez. Luego evalúa expresiones Xpath para localizar los elementos a procesar y saca las configuraciones en formato de texto. Los métodos XPathAPIselectNodeList y eval son llamados para evaluar expresiones XPath.

Código de ejemplo 17: El programa de procesamiento de documento XML basado en el API XPath (ChessboardXPathPrinter.java)

import javax.xml.parsers.*;
import javax.xml.transform.*;
import org.apache.xpath.*; 

public class ChessboardXPathPrinter {
 private DocumentBuilder builder;

 public void print(String fileName, PrintStream out)
   throws TransformerException, SAXException, ... {
  Document document = builder.parse(fileName);
  NodeList allPieces = XpathAPI.selectNodeList(
    document.getDocumentElement(),
    "//*[self::WHITEPIECES or self::BLACKPIECES]/*");
  for (int i = 0; i < allPieces.getLength(); i++) {
   Element piece = (Element) allPieces.item(i);
   Element pieces = (Element) piece.getParentNode();
   Element position 
     = (Element) piece.getChildNodes().item(0);
   out.println((pieces.getTagName()
     .equals("WHITEPIECES")
    ? "White " : "Black ")
   + piece.getTagName().toLowerCase()
   + ": " 
   + position.getAttribute("COLUMN")
   + position.getAttribute("ROW"));
   // out.println(XPathAPI.eval(piece,
   //  "concat(substring-before(name(..), \'PIECES\'),"
   //  + "\' \', name(),\': \',"
   //  + "[email protected], [email protected])"));
  }
  return;
 }
 ...
}

El método print primero usa una expresión XPath para localizar los elementos piece, luego los imprime usando el API DOM; la segunda expresión XPath que ha sido comentada podría haberse usado para el mismo propósito.

Este programa usa una expresión XPath para recuperar elementos que correspondan tanto con las piezas blancas como las negras (pattern "//*[self::WHITEPIECES" o "self::BLACKPIECES]/*"). Luego por cada elemento KING, QUEEN, BISHOP, ROOK, KNIGHT y PAWN recupera sus subelementos POSITION e imprime el color (basado en el nombre de la etiqueta abuelo), el nombre y la posición especificada por los atributos ROW y COLUMN.

. Programa de Ejemplo JDOM

En esta site, JDOM se presenta en los siguientes términos:

"JDOM es, simplemente, una representación Java de un documento XML. JDOM proporciona una forma de representar ese documento para una lectura, manipulación y escrituras fáciles y eficientes. Tiene un API correcto, es ligero y rápido, y está optimizado para el programador Java. Es una alternativa para DOM y SAX, aunque se integra bien con ámbos."

El siguiente programa que usa el API JDOM analiza y carga en memoria un documento XML que describe un conjuntro de configuraciones de tableros de ajedrez, luego pasa a través del documento JDOM resultante y saca las mismas configuraciones en formato texto. Se usa un SAXBuilder para crear un documento JDOM desde el documento fuente XML. Por defecto, el SAXBuilder de JDOM trabaja con JAXP para crear internamente un analizador SAX.

Código de ejemplo 18: El programa de procesamiento de documentos XML basado en el API JDOM (ChessboardJDOMPrinter.java)

import org.jdom.*;
import org.jdom.input.*;
import org.xml.sax.*;

public class ChessboardJDOMPrinter {
 private static boolean verbose = false;
 private SAXBuilder builder;

 public ChessboardJDOMPrinter(boolean validating)
   throws Exception {
  builder = new SAXBuilder();
  builder.setValidation(validating);
  ...
  return;
 }

 public void print(String fileName, PrintStream out)
   throws JDOMException {
  Document document = builder.build(fileName);
  Element root = document.getRootElement();
  List chessboards = root.getChildren("CHESSBOARD");
  for (int i = 0; i < chessboards.size(); i++) {
   Element chessboard = (Element) chessboards.get(i);
   String[] pieceSetTags = { "WHITEPIECES", 
     "BLACKPIECES" };
   for (int j = 0; j < pieceSetTags.length; j++) {
    List pieceSets 
= chessboard.getChildren(pieceSetTags[j]);
    for (int k = 0; k < pieceSets.size(); k++) {
     Element pieceSet = (Element) pieceSets.get(k);
     String[] pieceTags = { "KING", "QUEEN", "BISHOP",
    "ROOK", "KNIGHT", "PAWN" };
     for (int l = 0; l < pieceTags.length; l++) {
List pieces = pieceSet.getChildren(pieceTags[l]);
for (int m = 0; m < pieces.size(); m++) {
 Element piece = (Element) pieces.get(m);
 Element position = piece.getChild("POSITION");
 out.println(
   (j == 0 ? "White " : "Black ")
   + pieceTags[l].toLowerCase() + ": "
   + position.getAttributeValue("COLUMN")
   + position.getAttributeValue("ROW"));
}
     }
    }
   }
  }
  return;
 }
 ...
}

Este programa es muy similar al programa de ejemplo DOM. Baja por el árbol JDOM generado por el constructor de documentos desde el documento de entrada XML. Él:

  1. Obtiene todos los elementos CHESSBOARD.
  2. Por cada elemento CHESSBOARD obtiene los subelementos BLACKPIECES y WHITEPIECES.
  3. Por cada uno de los elementos BLACKPIECES y WHITEPIECES, obtiene los subelementos KING, QUEEN, BISHOP,ROOK, KNIGHT y PAWN.
  4. Por cada uuno de los elementos KING, QUEEN, BISHOP, ROOK, KNIGHT y PAWN imprime el color, el nombre y la posición especificada por los atributos ROW y COLUMN.

. Programa de Ejemplo YAXA

Este programa usa el API YAXA para analizar documentos XML que describen un conjunto de configuraciones de tableros de ajedrez, y saca las mismas configuraciones en formato texto. YAXA es un API experimental que funciona sobre SAX y añade el clasico paradigma Java Event/Source/Listener. El programa de abajo implementa el método elementStarted de un ElementEvent.Adapter. Este ElementEvent.Adapter está registrado con un XMLPathTracker (que es una subclase de DefaultHandler) y escucha ElementEvents que correspondan con un patrón específico:

Código de ejemplo 19: El programa de procesamiento de documento XML basado en el API YAXA (ChessboardYAXAPrinter.java)

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;
import yaxa.xml.*;
import yaxa.xml.events.*;

public class ChessboardYAXAPrinter {
 private SAXParser parser;

 public class ChessboardHandler
   extends XMLEventTracker {

  public ChessboardHandler() {
   addElementListener(new XMLEventTrack.Pattern(
     "//(WHITEPIECES|BLACKPIECES)/*/POSITION"),
     new ElementEvent.Adapter() {
public void elementStarted(ElementEvent event) {
 XMLEventTracker tracker 
   = (XMLEventTracker) event.getSource();
 XMLEventTrack.Builder builder
   = tracker.getCurrentTrackBuilder();
 String colorName 
   = builder.getEventName(builder.getLength()-3)
.equals("WHITEPIECES")
     ? "White " : "Black ");
 String pieceName
   = builder.getEventName(builder.getLength()-2);
 out.println(colorName + pieceName + ": "
   + event.getAttributes().getValue("COLUMN")
   + event.getAttributes().getValue("ROW"));
}
     });
   return;
  }
 }
}

Este programa captura todos los eventos de elementos que correspondan con un patrón específico ("//(WHITEPIECE|BLACKPIECE)/*/POSITION"). Luego por cada elemento que corresponda (es decir elementos POSITION) imprime el color, el nombre y la posición de la pieza correspondiente.

YAXA también implementa un editor de streams de eventos basado en el modelo anterior que edita directamente el flujo de eventos disparado por un analizador SAX.

Código de ejemplo 20: El programa usando el editor de streams YAXA XML para procesar configuraciones de tableros de ajedrez (ChessboardXSEPrinter.java)

import javax.xml.parsers.*;
import org.xml.sax.*;
import yaxa.xml.*;
import yaxa.editor.*;

public class ChessboardXSEPrinter {

 public static void main(String[] args) {
  ...
  XMLStreamEditor editor= new XMLStreamEditor(args[0]);
  XMLEventWriter writer = new XMLEventWriter("UTF-8",
    false,
    editor.getOutputFormat()
.equals(XMLEventWriter.TEXT_FORMAT),
    editor.isStrippingSpace());
  writer.setWriter(out);
  editor.setRedispatcher(writer);
  SAXParser parser
    = SAXParserFactory.newInstance().newSAXParser();
  parser.parse(args[1], editor);
  editor.clear();
  rewriter.flush();
  ...
 }
}

Código de ejemplo 21: El escript de edición de streams para transformación de documentos XML que representan configuraciones de tableros de ajedrez (ChessboardPrinter.xse)

<?xml version="1.0"?>

<!DOCTYPE xse:edit SYSTEM "file:./xse.dtd" >

<xse:edit>

 <xse:output xse:format="text" xse:strip-space="true" />

 <xse:print 
   xse:at='CHESSBOARDS/CHESSBOARD/WHITEPIECES/*/POSITION'
   xse:data="White $[track{-1}]: \
     $[[email protected]}]$[[email protected]}]" />

 <xse:print
   xse:at='CHESSBOARDS/CHESSBOARD/BLACKPIECES/*/POSITION'
   xse:data="Black $[track{-1}]: \
     $[[email protected]}]$[[email protected]}]" />

</xse:edit>

Este escript define dos comandos, uno que será disparado por cada pieza blanca (pattern "CHESSBOARDS/CHESSBOARD/WHITEPIECES/*/POSITION") y otro que será disparado por cada pieza negra (pattern "CHESSBOARDS/CHESSBOARD/BLACKPIECES/*/POSITION"). Estos comandos de edición realmente están implementados como oyentes de eventos que buscan esos eventos particulares. Cuando se dispara uno de estos comandos, inserta en el stream de eventos un nuevo evento de texto conteniendo un string, describiendo el color, el nombre y la posición de la pieza correspondiente. El stream de salida de eventos se escribe en texto normal.

. Generar Documentos XML

Hasta ahora, en este tutorial, nos hemos enfocado en analizar documentos XML de entrada y procesar las estructuras de datos resultantes explícita o implícitamente. Todavía no hemos cubierto la generación de documentos XML desde una estructura de datos interna -- la serialización a XML.

Para serializar una estructura de datos a XML, hay disponibles dos soluciones principales:

  • Generar el documento XML directamente "a mano".
  • Construir un árbol DOM o JDOM correspondiente y serializarlo para generar el documento XML.

La segunda solución es preferible porque nos asegura un documento limpio (no hay etiquetas sin cerrar). Además, tener un documento XML representado internamente como un árbol DOM, aunque requiere más recursos de memoria, permite un procesamiento posterior más eficiente, como la aplicación de hojas de estilo XSLT.

. Conclusión

En esta página hemos mostrado un ejemplo de las tecnologías disponibles para procesar documentos XML. Estas tecnologías se dirigien a diferentes niveles de abstracción y proporcionan diferentes niveles de utilización para el programador Java. Algunas de esta tecnologías como SAX, DOM, XPath y XSLT podrían relacionarse unas con otras. Por ejemplo, un constructor de documentos DOM podría usar un analizador SAX para generar un árbol DOM desde un documento XML, o un procesador XPath podría aplicar expresiones a un árbol DOM fuente, o un motor XSLT podría usar un procesador XPath para buscar y evaluar plantillas de hojas de estilo. Como se apilan, un desarrollador de aplicaciones XML podría verse tentado a elegir una de ellas para conseguir el mismo resultado, pero hacer esto traerá dificultades y pérdidas entre el rendimiento, el uso de memoria y la flexibilidad.

XSLT y XPath podrían trear flexibilidad a nuestra aplicación debido a su naturaleza de script, y podrían usarse para un proceso anterior y posterior de documentos XML generados y adquiridos por la aplicación. SAX podria traer eficiencia durante el mapeo de datos XML a objetos de negocio Java. DOM y especialmente JDOM podrían traer simplicidad y eficiencia en la edición de grandes modelos de documentos en memoria. En algunos casos, un modelo de objeto de documento podría ser elegible como la estructura de datos principal de la aplicación.

Todos estos APIs necesitan ser considerados cuando implementamos una aplicación XML. Además con el API SAX 2.0, y la intercambiabilidad (como fuente y resultado) de SAX y DOM en algunos APIs, se pueden construir complejas tuberías de procesamiento XML combinando implementaciones estándards y personalizadas.

COMPARTE ESTE ARTÍCULO

ENVIAR A UN AMIGO
COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN GOOGLE +
ARTÍCULO ANTERIOR

¡SÉ EL PRIMERO EN COMENTAR!
Conéctate o Regístrate para dejar tu comentario.