构造XPath? 算法XPath? 只有XPath

尊敬的读者您好。 这篇文章将专注于诸如XPath这样众所周知的形式主义的稍微非标准的应用程序。 每个人都知道从XML或HTML或其他* ML文档(简单文本和一些虚拟文本,它们代表任何复杂信息的顶层)提取信息非常方便,然后为了向这些文件提出任何问题。 但是,众所周知,问题的表达方式越好,答案中已经包含的部分就越多。 因此,一个简单的想法表明了自己:是否可以将用XPath编写的表达式用作断言,即以这种XPath表达式为真的方式构建文档? 我认为这是有可能的,这是这里将要讨论的第一件事。 第二点-如果我们学习如何通过直接使用XPath直接在文档中创建新元素,是否有可能将XPath变成一种简单的算法编程语言? 实际上,他知道如何访问数据,知道如何创建数据。 很容易想象如何描述运算符和分支运算符的顺序,而剩下的要考虑其中的循环和功能。 至少从理论上讲,这很有趣。 并且还将对此进行讨论。

构造XPath


因此,普通的XPath描述了在文档树中移动的一系列步骤,并且可以对每个步骤强加一个过滤条件(谓词写在方括号中)。 结果,我们得到了一些有限的节点集或一个数字或一个字符串或一个逻辑值。 我们主要对多个节点的情况感兴趣。 常规XPath生成文档中已经存在的节点。 考虑一个假想的XPath构造,该构造不仅将返回现有节点,还将构建新节点,以便它们与查询完全匹配。

这个想法非常简单-在XPath查询的下一步,我们将分析过滤器谓词并组成该过滤器下的数据变量。 然后,我们将检查其中哪些选项已经存在,并完成不存在的选项的构建。

例如,这是一个查询:

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

如果我们认为它是可构造的,那么首先我们将检查根元素<OBJS>是否存在,如果不存在,则创建它。 接下来是带有过滤器的步骤Var。 我不会描述处理谓词过滤器的规则,以免使表示复杂化,我只会说此过滤器清楚地描述了三个真实的数据集:

  1. <变量A =“ 1” B =“ 1” />
  2. <Var A =“ 2” />
  3. <Var A =“ 3” />

因此,我们需要确保<OBJS>元素具有带有此类数据的子<Var>元素。 最后,下一步是没有条件的X-这意味着每个Var元素都必须有一个子元素<X>。

因此,一切都很简单。 由于将这样的构造XPath应用于例如文档

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

我们得到输出文件:

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

同时,我们只使用XPath进行管理,而没有XSL或类似的东西。

算法XPath


因此,我们教了XPath如何创建数据。 现在教他(一点)对它们进行算法处理。

运算符的顺序可以通过通常的逻辑AND表达式来描述。 严格从左到右计算,这就是您所需要的。 如果必须完全实现它,则只需要确保其所有元素都返回一个真表达式即可。

 A and B and C … and Z 

形式为(A)则为B,否则为C的条件运算符,当然(我在这里不再赘述)可以通过逻辑表达式来描述
 A and B or C 

循环会使一切变得更加复杂。 我只是不想这样介绍它,所以我决定只介绍XPath函数的概念,它可以递归。 然后,可以将任何周期表示为带有终止条件验证的递归调用链。

原则上,这几乎是所有内容(最小版本)。 甚至不需要变量-它们被当前文档的元素所代替。 仅需要命名函数参数。

我举一个例子。 假设我们有一个包含两个数字列表的文档,这些列表由一系列嵌套的<list>元素描述:

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

让我们有必要串联来自<b>元素和<c>元素的列表,并将结果直接放在<a>中。 为此,必须引入三个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()) 

并将调用的XPath添加到它们:

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

希望亲爱的读者,对您理解这样的“代码”会有点有趣。 我肯定会提到的唯一一件事是create(XPATH)是一个在构造模式下执行其XPATH参数的系统函数。

现在,所有这些都很有趣,但是没有变量的编程仍然非常困难。 意识到这一点,我引入了完整的变量,实际上,它们在XPath中已经存在-它们以“ $”符号开头,但是我添加了使用新的set函数为其分配值的功能。 请使用以下带有两个参数的depth_list函数的示例-对包含嵌套元素列表的初始元素的引用(如上例所示),以及包含列表长度的输出变量:

 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() 

结论


在产生的微语言(我称为XPath Defender)中 ,我添加了一些其他必要的功能,并将其用于系统中以识别和生成PGEN ++程序,以执行诸如自动完成以XML文档形式呈现的程序模型之类的重要任务。 换句话说,如果存在问题的文本描述(为了确定性,用俄语),为此必须生成程序的解决方案,则此描述将被识别并转化为任务陈述元素(带有参数的对象)的有序集合。 这是初步声明,尚不包含解决问题的计划。 可识别的元素放置在XML文档中,并将规则应用于它们,以简单的边界或生成XPath语句的形式以及在XPath Defender上的片段的形式(这是工作流的选项之一)编写的。 这些规则使用解决方案计划的元素验证和补充XML文档模型。 然后只有根据获得的模型,系统才能构建决定性的程序。 该电路已经成功地测试了矢量数据数学处理的简单问题。

但是,尽管如此,我认为最重要的结果是,有可能证明有可能仅使用通常的方法并构造XPath来构建算法编程语言,仅引入功能是必要的。

Source: https://habr.com/ru/post/zh-CN464897/


All Articles