¿Hay algún procesador XPath para el modelo SAX?

Estoy buscando un evaluador XPath que no reconstruya todo el documento DOM para buscar los nodos de un documento: en realidad, el objective es administrar una gran cantidad de datos XML (idealmente más de 2 Gb) con el modelo SAX, que es muy bueno para la gestión de memoria, y da la posibilidad de buscar nodos.

¡Gracias por todo el apoyo!

Para todos aquellos que dicen que no es posible: Recientemente, después de hacer la pregunta, encontré un proyecto llamado “saxpath” ( http://www.saxpath.org/ ), pero no encuentro ningún proyecto de implementación.

Mi lista actual (comstackda a partir de resultados de búsqueda web y las otras respuestas) es:

El siguiente paso es usar los ejemplos de XMLDog y comparar el rendimiento de todos estos enfoques. Luego, los casos de prueba deberían extenderse a las expresiones XPath soportadas.

Analizamos regularmente archivos XML complejos de 1GB + utilizando un analizador SAX que extrae árboles DOM parciales que pueden consultarse convenientemente usando XPath. Bloggeé sobre esto aquí: http://softwareengineeringcorner.blogspot.com/2012/01/conveniently-processing-large-xml-files.html – Las fonts están disponibles en github – Licencia MIT.

XPath SI trabaja con SAX, y la mayoría de los procesadores XSLT (especialmente Saxon y Apache Xalan) admiten la ejecución de expresiones XPath dentro de XSLT en una secuencia SAX sin construir toda la dom.

Logran hacer esto, muy aproximadamente, de la siguiente manera:

  1. Examinando las expresiones XPath que necesitan para coincidir
  2. Recepción de eventos SAX y prueba si ese nodo es necesario o lo necesitará una de las expresiones XPath.
  3. Ignorar el evento SAX si no sirve para las expresiones XPath.
  4. Buffering si es necesario

También es muy interesante cómo lo almacenan, porque algunos simplemente crean fragmentos de DOM aquí y allá, otros usan tablas muy optimizadas para una búsqueda rápida y un consumo de memoria reducido.

Lo mucho que logran optimizar depende en gran medida del tipo de consultas XPath que encuentren. Como la documentación sajona ya publicada explica claramente, las consultas que se mueven “hacia arriba” y luego recorren “horizontalmente” (hermano por hermano) el documento obviamente requiere que todo el documento esté allí, pero la mayoría de ellos requieren solo unos pocos nodos para guardarlos. RAM en cualquier momento.

Estoy bastante seguro de esto porque cuando todavía estaba haciendo webapp todos los días utilizando Cocoon, teníamos el problema de huella de memoria XSLT cada vez que usábamos una expresión “// something” dentro de un XSLT, y con bastante frecuencia teníamos que volver a trabajar en expresiones XPath para permitir una mejor optimización de SAX.

SAX es solo hacia adelante, mientras que las consultas XPath pueden navegar por el documento en cualquier dirección (considere parent:: , ancestor:: , preceding:: y preceding-sibling:: eje). No veo cómo esto sería posible en general. La mejor aproximación sería algún tipo de DOM de carga diferida, pero dependiendo de sus consultas esto puede proporcionarle algún beneficio, siempre hay una peor de las consultas como //*[. != preceding::*] //*[. != preceding::*] .

Lo siento, una respuesta un poco tarde aquí – parece que esto es posible para un subconjunto de XPath – en general es muy difícil debido al hecho de que XPath puede coincidir tanto hacia delante como hacia atrás desde el punto “actual”. Conozco dos proyectos que lo resuelven hasta cierto punto usando máquinas de estado: http://spex.sourceforge.net y http://www.cs.umd.edu/projects/xsq . No los he analizado en detalle, pero parecen utilizar un enfoque similar.

Lanzaré un enchufe para un nuevo proyecto mío, llamado AXS. Está en https://code.google.com/p/annotation-xpath-sax/ y la idea es que anote métodos con declaraciones XPath (solo para el eje hacia adelante) y se invoquen cuando el analizador SAX esté en un nodo eso lo iguala. Entonces con un documento

   text of node 1 text of node 2 text of node 3   

puedes hacer cosas como

 @XPath("/nodes/node") void onNode(String nodeText) { // will be called with "text of node [123]" } 

o

 @XPathStart("//node[@name='']") void onNode3(Attrs node3Attrs) { ... } 

o

 @XPathEnd("/nodes/node[2]") void iDontCareAboutNode3() throws SAXExpression { throw new StopParsingExpression(); } 

Por supuesto, la biblioteca es tan nueva que aún no la he lanzado, pero está licenciada por MIT, así que siéntete libre de probarla y ver si coincide con tus necesidades. (Lo escribí para hacer raspado de pantalla HTML con requisitos de memoria lo suficientemente bajos como para poder ejecutarlo en viejos dispositivos Android …) ¡Si encuentra errores, hágamelo saber archivándolos en el sitio googlecode!

Perdón por la respuesta tardía, pero implementé una simple ruta de expresión XPath para los analizadores SAX. Solo admite etiqueta, atributo con valor opcional e índice debido a la naturaleza de reenvío de SAX. Hice un Handler de delegado para evaluar la expresión dada cuando el Handler implementa ExpressionFilter . Aunque estas clases están integradas en el proyecto, no debería ser difícil de extraer.

Más información

Ejemplos : consulte las clases con el prefijo HandlerHtml

Existen implementaciones XPath basadas en SAX / StAX, pero solo admiten un pequeño subconjunto de expresiones / ejes XPath en gran parte debido a la naturaleza de reenvío de SAX / StAX. La mejor alternativa que conozco es la VTD-XML extendida, es compatible con xpath completo. carga parcial de documentos a través de mem-map .. y un tamaño máximo de documento de 256 GB, pero necesitará una JVM de 64 bits para usarla en todo su potencial

Lo que podría hacer es conectar un transformador XSL a una fuente de entrada SAX. Su procesamiento será secuencial y el preprocesador XSL intentará capturar la entrada, ya que se trata de virar en cualquier resultado que haya especificado. Puede usar esto para extraer el valor de una ruta fuera de la secuencia. Esto sería especialmente útil si quisieras producir un montón de diferentes resultados de XPATH en una sola pasada.

Obtendrá (normalmente) un documento XML como resultado, pero podría sacar su salida esperada de, por ejemplo, un StreamResult sin demasiadas molestias.

Eche un vistazo al modo de transmisión del procesador XSLT Saxon-SA.

http://www.saxonica.com/documentation/sourcedocs/serial.html

“Las reglas que determinan si una expresión de ruta se puede transmitir son:

  • La expresión a ser transmitida comienza con una llamada en la función document () o doc ().
  • La expresión de ruta introducida por la llamada en doc () o documento debe ajustarse a un subconjunto de XPath definido de la siguiente manera:

  • cualquier expresión XPath es aceptable si cumple con las reglas para las expresiones de ruta que aparecen en las restricciones de identidad en el Esquema XML. Estas reglas no permiten predicados; el primer paso (pero solo el primero) se puede introducir con “//”; el último paso puede usar opcionalmente el eje de atributo; todos los demás pasos deben ser simples Axis Steps utilizando el eje secundario.

  • Además, Saxon permite que la expresión contenga una unión, por ejemplo doc () / (* / ABC | / XYZ). Las uniones también se pueden express en forma abreviada, por ejemplo, lo anterior se puede escribir como doc () / / (ABC | XYZ).
  • La expresión debe seleccionar solo elementos, o solo atributos, o una combinación de elementos y atributos.

  • Los filtros simples (uno o más) también son compatibles. Cada filtro puede aplicarse al último paso o a la expresión como un todo, y solo debe usar la selección descendente desde el nodo de contexto (el auto, secundario, atributo, descendiente, descendiente o auto, o los ejes del espacio de nombres). No debe ser posicional (es decir, no debe hacer referencia a position () o last (), y no debe ser numérico: de hecho, debe ser tal que Saxon pueda determinar en tiempo de comstackción que no será numérico). Los filtros no pueden aplicarse a sindicatos o sucursales de sindicatos. Cualquier violación de estas condiciones hace que la expresión sea evaluada sin la optimización de transmisión.

  • Estas reglas se aplican después de que se hayan aplicado otras reescrituras de optimización a la expresión. Por ejemplo, algunas expresiones FLWOR pueden reescribirse a una expresión de ruta que satisfaga estas reglas.

  • La optimización solo se habilita si se solicita explícitamente, ya sea utilizando la función de extensión saxon: stream (), o el atributo saxon: read-once en una instrucción xSLT xsl: copy-of, o XQuery pragma saxon: stream. Está disponible solo si la hoja de estilo o consulta se procesa usando Saxon-SA. ”

Nota: Es muy probable que en la versión comercial este servicio esté disponible. He usado Saxon mucho antes, y es una buena pieza de trabajo.

Mmh, no sé si realmente te entiendo. Por lo que sé, el modelo SAX está orientado a eventos. Eso significa que haces algo si se encuentra un determinado nodo durante el análisis sintáctico. Sí, es mejor para la memoria, pero no veo cómo te gustaría poner XPath en ella. Como SAX no construye un modelo, no creo que esto sea posible.

La API javax xpath estándar técnicamente ya funciona con transmisiones; javax.xml.xpath.XPathExpression se puede evaluar en un InputSource , que a su vez se puede construir con un Reader . No creo que construya un DOM bajo las sábanas.

¿Has probado también QuiXPath https://code.google.com/p/quixpath/ ?

No creo que xpath funcione con SAX, pero podría echarle un vistazo a StAX, que es una API XML de transmisión extendida para Java.

http://en.wikipedia.org/wiki/StAX