2008-12-10 11 views
18

(Todo lo que sigue es que ser escrito en Java)de análisis muy grandes documentos XML (y un poco más) en java

Tengo que construir una aplicación que tendrá como documentos XML de entrada que son, potencialmente, muy grande. El documento está encriptado, no con XMLsec, pero con el algoritmo de cifrado preexistente de mi cliente. Se procesará en tres fases:

Primero, la secuencia se descifrará de acuerdo con el algoritmo mencionado anteriormente.

En segundo lugar, una clase de extensión (escrita por un tercero en una API que estoy proporcionando) leerá una parte del archivo. La cantidad que se lee no es predecible; en particular, no se garantiza que esté en el encabezado del archivo, pero puede ocurrir en cualquier punto del XML.

Por último, otra clase de extensión (misma oferta) subdividirá el XML de entrada en documentos de subconjuntos 1..n. Es posible que en alguna parte se superpongan con la parte del documento tratada por la segunda operación, es decir: creo que tendré que rebobinar cualquier mecanismo que esté utilizando para tratar con este objeto.

Aquí es mi pregunta:

¿Hay una manera de hacer esto sin tener que leer todo el trozo de datos en la memoria al mismo tiempo? Obviamente, puedo implementar el descifrado como un filtro de flujo de entrada, pero no estoy seguro de si es posible analizar XML en la forma en que estoy describiendo; al recorrer la mayor parte del documento para recopilar la información del segundo paso y, a continuación, rebobinar el documento y volver a pasarlo para dividirlo en trabajos, idealmente liberando todas las partes del documento que ya no se utilizan después ellos han sido pasados

Respuesta

3

Puede usar un BufferedInputStream con un tamaño de búfer muy grande y usar mark() antes de que la clase de extensión funcione y reset() después.

Si las partes que la clase de extensión necesita están muy lejos en el archivo, entonces esto podría requerir una gran cantidad de memoria.

Una solución más general sería escribir su propio BufferedInputStream -al igual que los búferes en el disco si los datos que se almacenan en el búfer exceden algún umbral preestablecido.

1

Quizás se encuentre interesado por XOM:

XOM es bastante único, ya que es una API transmisión dual/basado en árboles. Nodos individuales en el árbol pueden ser procesados ​​mientras el documento todavía está siendo construido . Permite que los programas de XOM funcionen casi tan rápido como el analizador subyacente puede suministrar datos. Usted no necesita esperar a que el documento sea completamente analizado antes de poder comenzar a trabajar con él.

XOM es muy eficiente en la memoria. Si lee un documento completo en la memoria, XOM usa la menor cantidad de memoria posible. Más importante aún, XOM le permite documentos de filtro, ya que están construidos de modo que no tiene que construir las partes de el árbol que no le interesa.Para la instancia , puede omitir los nodos del texto de construcción que solo representan el espacio en blanco del límite , si dicho espacio en blanco es no significativo en su aplicación. Incluso puede procesar una pieza de documento por pieza y tirar cada pieza cuando haya terminado con ella. XOM ha sido utilizado para procesar documentos que tienen un tamaño de gigabytes.

+1

Parece un enfoque interesante y potencialmente útil, pero en ninguna parte de la documentación allí sugiere una forma de controlar el análisis del documento en la forma descrita. Creo que puede, pero la capacidad de no está documentada de una manera razonable de descubrir. –

7

Esto suena como un trabajo para StAX (JSR 173). StAX es un analizador de extracción, lo que significa que funciona más o menos como un analizador basado en eventos como SAX, pero que tiene más control sobre cuándo dejar de leer, qué elementos extraer, ...

La usabilidad de este La solución dependerá mucho de lo que realmente hagan sus clases de extensión, si tiene control sobre su implementación, etc.

El punto principal es que si el documento es muy grande, es probable que desee utilizar un evento basado analizador y no basado en un árbol, por lo que no usará mucha memoria.

Las implementaciones de StAX se pueden encontrar desde SUN (SJSXP), Codehaus o algunos otros proveedores.

+0

Esto parece prometedor, siempre y cuando pueda conectarlo eficientemente. Parece que tendré que exponer StAX a los clientes de mi API, que es menos que ideal, pero al menos parece que las capacidades están ahí. ¿Puedes modificar tu publicación con una implementación recomendada, en lugar de la lista? –

+1

Sé que esta es una respuesta/comentario anterior, pero hay algunas librerías que pueden agregar un poco más de comodidad sobre el stax (y aislar algunos detalles de nivel inferior), por ejemplo StaxMate [http://staxmate.codehaus.org/Tutorial ] Esto aún permite el análisis/escritura incremental, pero reduce la cantidad de código para escribir. – StaxMan

3

me gustaría escribir una implementación personalizada de InputStream que descifra los bytes en el archivo y luego usar SAX para analizar el XML resultante como sale la corriente.

SAXParserFactory.newInstance().newSAXParser().parse(
    new DecryptingInputStream(), 
    new MyHandler() 
); 
0

Mire la biblioteca XOM. El ejemplo que está buscando es StreamingExampleExtractor.java en el directorio de ejemplos de la distribución fuente. Esto muestra una técnica para realizar un análisis de transmisión de un documento xml grande que solo crea nodos específicos, los procesa y los descarta. Es muy similar a un enfoque sax, pero tiene una capacidad de análisis mucho más integrada, por lo que se puede lograr un análisis de transmisión con bastante facilidad.

Si desea trabajar en un nivel superior, mire NUX. Esto proporciona una API de transmisión xpath de alto nivel que solo lee la cantidad de datos en la memoria necesaria para evaluar el xpath.

Cuestiones relacionadas