2009-06-15 24 views
13

¿Existen bibliotecas preparadas para la producción para la transmisión de la evaluación de expresiones XPath con el 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.Streaming evaluación de XPath

+1

ETV-XML tiene el único apoyo XPath que no se construye sobre DOM, es más eficiente de la memoria ... –

+0

Thaks mucho, he visto su proyecto antes. Parece prometedor – nixau

+0

Hay alguna información nueva sobre este tema - ver mi respuesta. –

Respuesta

3

Sería ésta práctica para una implementación completa de XPath, dado que la sintaxis XPath permite:

/AAA/XXX/following::* 

y

/AAA/BBB/following-sibling::* 

que implica Look-Ahead requisitos? es decir, desde un nodo particular, tendrá que cargar el resto del documento de todos modos.

El documento para la Nux biblioteca (específicamente StreamingPathFilter) hace de este punto, y las referencias en 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.

+0

En realidad, necesito ejecutar consultas simples xpath que verifiquen varios nodos en un documento xml dado para fines de validación. El documento Xml representa una entidad y algunos de sus nodos almacenan claves externas a otras entidades. Y como resultado, se debe aplicar algún tipo de validación de intergity contra estos nodos especiales. El documento global es bastante grande y sería poco eficiente almacenar dicha cantidad de datos en memoria para la ejecución de varias consultas simples de xpath. – nixau

+1

Parece que la biblioteca Nux puede ayudarle en este escenario. Alternativamente, ¿podría usar una biblioteca Stax y aplicar el XPath al documento XML local que extrae de un determinado nodo? –

+0

En realidad, no puedo emplear el segundo enfoque, porque la estructura del documento xml es relativamente simple y no tiene sentido extraer un nodo del documento y aplicar la expresión xpath en su contra. – nixau

3

Hay varias opciones:

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

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

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

0

Fwiw, he utilizado Nux consultas XPath filtro de transmisión en contra muy grandes (> 3 GB) archivos, y es a la vez funcionó a la perfección y se utiliza 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.

1

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

0

Creo que voy a buscar un código personalizado. La biblioteca .NET nos acerca bastante al objetivo, si uno solo quiere leer algunas rutas del documento xml.

Dado que todas las soluciones que veo hasta ahora respetan solo 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 con una ruta explícita. También puede operar los atributos fácilmente, usando la sintaxis 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<String>(); 
    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();