¿Construyendo XPath? XPath algorítmico? Nada más que XPath

Hola queridos lectores. Esta publicación se centrará en aplicaciones ligeramente no estándar de un formalismo tan conocido como XPath. Todo el mundo sabe que es muy conveniente extraer información de XML o HTML u otros * documentos ML (tanto texto plano como algunos virtuales, que son la capa superior para representar cualquier información compleja), luego Hay para hacer estos documentos cualquier pregunta. Sin embargo, se sabe que cuanto mejor se formula la pregunta, más parte de la respuesta ya contiene. Por lo tanto, se sugiere un pensamiento simple: ¿es posible usar expresiones escritas en XPath como afirmativas, es decir, construir un documento de tal manera que esta expresión XPath sea verdadera? Creo que es posible, y esto es lo primero que se discutirá aquí. Y la segunda: si aprendemos cómo crear directamente nuevos elementos en un documento utilizando XPath directamente, ¿es posible convertir XPath en un lenguaje de programación algorítmico simple? De hecho, él sabe cómo acceder a los datos, sabe cómo crearlos. Es fácil imaginar cómo describir la secuencia de operadores y el operador de rama en él, queda por pensar en los ciclos y las funciones. Esto es interesante, al menos teóricamente. Y esto también se discutirá.

Construyendo XPath


Entonces, XPath ordinario describe una secuencia de pasos para moverse a través de un árbol de documentos, y se puede imponer una condición de filtro (un predicado entre corchetes) en cada paso. Como resultado, obtenemos un conjunto finito de nodos o un número o una cadena o un valor lógico. Estamos principalmente interesados ​​en el caso de múltiples nodos. XPath regular produce nodos que ya existen en el documento. Considere una XPath de construcción hipotética que no solo devolverá nodos existentes, sino que también generará nuevos nodos de tal manera que coincidan completamente con la consulta.

La idea es muy simple: en el siguiente paso de la consulta XPath, analizaremos el predicado del filtro y compondremos las variantes de datos que se incluyen en este filtro. Y luego comprobaremos cuáles de estas opciones ya existen y terminaremos de construir las inexistentes.

Por ejemplo, aquí hay una consulta:

/OBJS/Var[@A=1 and @B=1 or @A=2 or @A=3]/X 

Si lo consideramos como una construcción, primero comprobaremos si el elemento raíz <OBJS> existe, y si no, lo crearemos. Luego viene el paso Var con un filtro. No describiré las reglas por las cuales se procesa el filtro de predicados para no complicar la presentación, solo diré que este filtro describe claramente los tres conjuntos de datos en los que es cierto:

  1. <Var A = ”1” B = ”1” />
  2. <Var A = "2" />
  3. <Var A = "3" />

Por lo tanto, debemos asegurarnos de que el elemento <OBJS> tenga elementos secundarios <Var> con dichos datos. Y, finalmente, el siguiente paso es X sin una condición: esto significa que es necesario que cada elemento Var tenga un elemento hijo <X>.

Entonces, todo es simple. Como resultado de aplicar tal XPath de construcción, por ejemplo, a un documento

 <OBJS> <Var A=”2” /> </OBJS> 

obtenemos el documento de salida:

 <OBJS> <Var A=”2”> <X/> </Var> <Var A=”1” B=”1”> <X/> </Var> <Var A=”3”> <X/> </Var> </OBJS> 

Y al mismo tiempo, nos las arreglamos exclusivamente con XPath, sin XSL ni nada de eso.

XPath Algorítmico


Entonces enseñamos a XPath cómo crear datos. Ahora enséñele (un poco) a procesarlos algorítmicamente.

La secuencia de operadores se puede describir mediante una expresión AND lógica habitual. Se calcula estrictamente de izquierda a derecha, esto es lo que necesita. Si debe implementarse por completo, solo debe asegurarse de que todos sus elementos devuelvan una expresión verdadera.

 A and B and C … and Z 

Un operador condicional de la forma si (A) entonces B más C , por supuesto (y no diré nada nuevo aquí), puede describirse mediante una expresión lógica
 A and B or C 

Todo es un poco más complicado con el bucle. Simplemente no quería presentarlo así, así que decidí presentar el concepto de una función XPath, que puede ser recursiva. Y luego, cualquier ciclo puede representarse como una cadena de llamadas recursivas con verificación de la condición de terminación.

En principio, esto es casi todo (en la versión mínima). Ni siquiera se requieren variables: se reemplazan por elementos del documento actual. Solo se requieren argumentos de funciones con nombre.

Daré un ejemplo. Supongamos que tenemos un documento que contiene dos listas de números descritos por una serie de elementos <list> anidados:

  <a> <b> <list data="1"><list data="2"></list></list> </b> <c> <list data="3"><list data="4"></list></list></c> </a> 

Sea necesario concatenar listas del elemento <b> y el elemento <c> y colocar el resultado directamente en <a>. Para hacer esto, se deben introducir tres funciones XPath:

 concat_list($#, $##): add_list(#/self::*) and add_list(##/self::*) add_list($#): count(list) = 0 and copy_list(#/self::*) or list[add_list(#/self::*)] or true() copy_list($#): count(#/list) = 0 or create(list[@data = #/list/@data]) and (list[copy_list(#/list)] or true()) 

y agregue el XPath que llama a ellos:

 concat_list(/a/b,/a/c) 

Espero que, queridos lectores, les resulte un poco interesante entender ese "código". Lo único que definitivamente mencionaré: create (XPATH) es una función del sistema que ejecuta su argumento XPATH en modo construcción.

Y ahora que todo esto es interesante, por supuesto, pero la programación sin variables sigue siendo bastante difícil. Entendiendo esto, introduje variables completas, que, de hecho, en XPath ya existen: comienzan con el signo "$", pero agregué la capacidad de asignarles valores con la nueva función de conjunto. Por favor, aquí hay un ejemplo de la función depth_list con dos argumentos: una referencia al elemento inicial que contiene una lista anidada de elementos (como en el ejemplo anterior) y una variable de salida que contiene la longitud de la lista:

 depth_list($#, &$OUT1): set($OUT1,0) and (#/list[set($OUT1,1) and depth_list(#/list,$OUT0) and set($OUT1,max($OUT0+1,$OUT1))]) or true() 

Conclusión


En el micro lenguaje resultante, que llamé XPath Defender , agregué algunas funciones más necesarias y lo usé en mi sistema para reconocer y generar programas PGEN ++ para realizar una tarea tan importante como la finalización automática del modelo de un programa presentado como un documento XML. En otras palabras, si hay una descripción textual de un problema (por definición, en ruso), para cuya solución es necesario generar un programa, esta descripción se reconoce y se convierte en un conjunto ordenado de elementos de declaración de tareas (objetos con parámetros). Esta es la declaración inicial, que aún no contiene un plan para resolver el problema. Los elementos reconocidos se colocan en un documento XML y se les aplican las reglas, escritos en forma de límites simples o generando declaraciones XPath, y en forma de fragmentos en XPath Defender (esta es una de las opciones para el flujo de trabajo). Estas reglas validan y complementan el modelo de documento XML con elementos de un plan de solución. Y solo entonces, según el modelo obtenido, el sistema construye un programa decisivo. Este circuito ha sido probado con éxito en problemas simples de procesamiento matemático de datos vectoriales.

Pero aún así, el resultado más importante, creo, es el hecho de que fue posible demostrar que es posible construir un lenguaje de programación algorítmica, utilizando casi exclusivamente los medios del XPath habitual y de construcción, fue necesario introducir solo funciones.

Source: https://habr.com/ru/post/464897/


All Articles