Evaluación de streaming XPath

¿Hay alguna biblioteca preparada para la producción para la transmisión de la evaluación de expresiones XPath en función del documento xml proporcionado? Mis investigaciones muestran que la mayoría de las soluciones existentes cargan todo el árbol DOM en la memoria antes de evaluar la expresión xpath.

¿Sería esto práctico para una implementación completa de XPath, dado que la syntax de XPath permite:

/AAA/XXX/following::* 

y

 /AAA/BBB/following-sibling::* 

¿Qué implica requisitos de anticipación? es decir, desde un nodo en particular, tendrá que cargar el rest del documento de todos modos.

El documento para la biblioteca Nux (específicamente StreamingPathFilter ) señala este punto y hace referencia a algunas implementaciones que se basan en un subconjunto de XPath. Nux afirma realizar algunas funciones de consulta de transmisión, pero dado lo anterior, habrá algunas limitaciones en cuanto a la implementación de XPath.

XSLT 3.0 proporciona un modo de procesamiento de transmisión y esto se convertirá en un estándar con la especificación W3C de XSLT 3.0 convirtiéndose en una Recomendación W3C.

En el momento de escribir esta respuesta (mayo de 2011), Saxon ofrece algo de soporte para la transmisión XSLT 3.0 .

Hay varias opciones:

  • DataDirect Technologies vende una implementación XQuery que emplea proyección y transmisión, siempre que sea posible. Puede manejar archivos en el rango de varios gigabytes, por ejemplo, más grande que la memoria disponible. Es una biblioteca segura para subprocesos, por lo que es fácil de integrar. Solo en Java

  • Saxon es una versión de código abierto, con un primo más caro y de precio modesto, que hará streaming en algunos contextos. Java, pero con un puerto .net también.

  • MarkLogic y eXist son bases de datos XML que, si su XML está cargado en ellas, procesará XPaths de una manera bastante inteligente.

Prueba Joost .

Aunque no tengo experiencia práctica con esto, pensé que vale la pena mencionar QuiXProc ( http://code.google.com/p/quixproc/ ). Es un enfoque de transmisión a XProc, y utiliza bibliotecas que brindan soporte de transmisión para XPath entre otros.

FWIW, he usado Nux streaming filter xpath consultas contra archivos muy grandes (> 3GB), y ambos han funcionado sin problemas y han usado muy poca memoria. Mi caso de uso ha sido ligeramente diferente (no centrado en la validación), pero te animo a que lo pruebes con Nux.

Creo que iré por código personalizado. La biblioteca .NET nos acerca bastante al objective, si uno solo quiere leer algunas rutas del documento xml.

Como todas las soluciones que veo hasta ahora solo respetan el subconjunto XPath, este es también este tipo de solución. Sin embargo, el subconjunto es realmente pequeño. 🙂

Este código C # lee el archivo xml y cuenta los nodos a los que se asigna una ruta explícita. También puede operar con atributos fácilmente, usando la syntax xr["attrName"] .

  int c = 0; var r = new System.IO.StreamReader(asArgs[1]); var se = new System.Xml.XmlReaderSettings(); var xr = System.Xml.XmlReader.Create(r, se); var lstPath = new System.Collections.Generic.List(); var sbPath = new System.Text.StringBuilder(); while (xr.Read()) { //Console.WriteLine("type " + xr.NodeType); if (xr.NodeType == System.Xml.XmlNodeType.Element) { lstPath.Add(xr.Name); } // It takes some time. If 1 unit is time needed for parsing the file, // then this takes about 1.0. sbPath.Clear(); foreach(object n in lstPath) { sbPath.Append('/'); sbPath.Append(n); } // This takes about 0.6 time units. string sPath = sbPath.ToString(); if (xr.NodeType == System.Xml.XmlNodeType.EndElement || xr.IsEmptyElement) { if (xr.Name == "someElement" && lstPath[0] == "main") c++; // And test simple XPath explicitly: // if (sPath == "/main/someElement") } if (xr.NodeType == System.Xml.XmlNodeType.EndElement || xr.IsEmptyElement) { lstPath.RemoveAt(lstPath.Count - 1); } } xr.Close();