Olá queridos leitores. Esta postagem se concentrará em aplicativos levemente não padronizados de um formalismo conhecido como XPath. Todo mundo sabe que é muito conveniente extrair informações de XML ou HTML ou de alguns outros documentos * ML (texto simples e alguns virtuais, que são a camada superior da representação de qualquer informação complexa); existe para fazer perguntas a esses documentos. No entanto, sabe-se que quanto melhor a pergunta é formulada, mais parte da resposta já contém. Portanto, um pensamento simples se sugere: é possível usar expressões escritas no XPath como afirmando, ou seja, construindo um documento de tal maneira que essa expressão XPath seja verdadeira? Eu acho que é possível, e esta é a primeira coisa que será discutida aqui. E a segunda - se aprendermos a criar diretamente novos elementos em um documento usando o XPath diretamente, é possível transformar o XPath em uma linguagem de programação algorítmica simples? De fato, ele sabe como acessar dados, ele sabe como criar dados. É fácil imaginar como descrever a sequência de operadores e o operador de filial nela; resta pensar nos ciclos nela e nas funções. Isso é interessante, pelo menos teoricamente. E isso também será discutido.
Construindo XPath
Portanto, o XPath comum descreve uma sequência de etapas para mover-se através de uma árvore de documentos, e uma condição de filtro (um predicado escrito entre colchetes) pode ser imposta em cada etapa. Como resultado, obtemos um conjunto finito de nós ou um número ou uma string ou um valor lógico. Estamos interessados principalmente no caso de vários nós. XPath regular produz nós que já existem no documento. Considere um XPath de construção hipotético que não apenas retornará nós existentes, mas também crie novos nós para que correspondam totalmente à consulta.
A idéia é muito simples - na próxima etapa da consulta XPath, analisaremos o predicado do filtro e compilaremos as variantes de dados que se enquadram nesse filtro. E então verificaremos quais dessas opções já existem e concluiremos a construção de opções inexistentes.
Por exemplo, aqui está uma consulta:
/OBJS/Var[@A=1 and @B=1 or @A=2 or @A=3]/X
Se considerarmos isso como construção, primeiro verificaremos se o elemento raiz <OBJS> existe e, se não, criaremos. Em seguida, vem a etapa Var com um filtro. Não descreverei as regras pelas quais o filtro de predicado é processado para não complicar a apresentação, apenas direi que esse filtro descreve claramente os três conjuntos de dados nos quais é verdadeiro:
- <Var A = ”1” B = ”1” />
- <Var A = "2" />
- <Var A = ”3” />
Portanto, precisamos garantir que o elemento <OBJS> tenha elementos filho <Var> com esses dados. E, finalmente, o próximo passo é X sem uma condição - isso significa que é necessário que cada elemento Var tenha um elemento filho <X>.
Então, tudo é simples. Como resultado da aplicação de um XPath de construção, por exemplo, a um documento
<OBJS> <Var A=”2” /> </OBJS>
nós obtemos o documento de saída:
<OBJS> <Var A=”2”> <X/> </Var> <Var A=”1” B=”1”> <X/> </Var> <Var A=”3”> <X/> </Var> </OBJS>
E, ao mesmo tempo, gerenciamos exclusivamente com XPath, sem XSL ou qualquer coisa assim.
XPath algorítmico
Então, ensinamos o XPath a criar dados. Agora ensine-o (um pouco) a processá-los algoritmicamente.
A sequência de operadores pode ser descrita por uma expressão AND lógica usual. É calculado estritamente da esquerda para a direita, é isso que você precisa. Se for necessário implementá-lo completamente, basta garantir que todos os seus elementos retornem uma expressão verdadeira.
A and B and C … and Z
Um operador condicional do formulário
se (A) então B else C , é claro (e não direi nada de novo aqui), pode ser descrito por uma expressão lógica
A and B or C
Tudo é um pouco mais complicado com o loop. Como não queria apresentá-lo dessa maneira, decidi apenas apresentar o conceito de uma função XPath, que pode ser recursiva. E então qualquer ciclo pode ser representado como uma cadeia de chamadas recursivas com verificação da condição de término.
Em princípio, isso é quase tudo (na versão mínima). Nem mesmo as variáveis são necessárias - elas são substituídas por elementos do documento atual. Apenas argumentos de função nomeada são necessários.
Eu darei um exemplo Suponha que tenhamos um documento contendo duas listas de números descritos por uma série de elementos <list> aninhados:
<a> <b> <list data="1"><list data="2"></list></list> </b> <c> <list data="3"><list data="4"></list></list></c> </a>
Seja necessário concatenar listas dos elementos <b> e <c> e coloque o resultado diretamente em <a>. Para fazer isso, três funções XPath devem ser introduzidas:
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())
e adicione o XPath de chamada a eles:
concat_list(/a/b,/a/c)
Espero que, queridos leitores, seja um pouco interessante para você entender esse "código". A única coisa que definitivamente mencionarei é
create (XPATH) é uma função do sistema que executa seu argumento XPATH no modo de construção.
E agora que tudo isso é interessante, é claro, mas programar sem variáveis ainda é bastante difícil. Percebendo isso, introduzi variáveis completas, que, de fato, no XPath já existem - elas começam com o sinal "$", mas acrescentei a capacidade de atribuir valores a elas com a nova função de conjunto. Por favor, aqui está um exemplo da função depth_list com dois argumentos - uma referência ao elemento inicial que contém uma lista aninhada de elementos (como no exemplo acima) e uma variável de saída que contém o comprimento da 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()
Conclusão
Na micro-linguagem resultante, que chamei
XPath Defender , adicionei algumas funções mais necessárias e usei-a no meu sistema para reconhecer e gerar programas PGEN ++ para executar uma tarefa tão importante como a conclusão automática do modelo de um programa apresentado como um documento XML. Em outras palavras, se houver uma descrição textual de um problema (para definição, em russo), cuja solução é necessária para gerar um programa, essa descrição será reconhecida e se transformará em um conjunto ordenado de elementos de instrução de tarefa (objetos com parâmetros). Esta é a declaração inicial, que ainda não contém um plano para resolver o problema. Os elementos reconhecidos são colocados em um documento XML e as regras são aplicadas a eles, escritas na forma de instruções XPath limitantes ou geradoras simples e na forma de fragmentos no XPath Defender (essa é uma das opções para o fluxo de trabalho). Essas regras validam e complementam o modelo de documento XML com elementos de um plano de solução. E só então, de acordo com o modelo obtido, o sistema constrói um programa decisivo. Este circuito foi testado com sucesso em problemas simples de processamento matemático de dados vetoriais.
Mas, no entanto, o resultado mais importante, eu acho, é o fato de que foi possível provar que é possível construir uma linguagem de programação algorítmica, usando quase exclusivamente os meios do XPath usual e construindo, era necessário introduzir apenas funções.