[IR] XPath for Search Query

XPath 1.0

XPath Containment

Distributed Query Evaluation

RE and DFA


 

XPath 1.0 

-- 在XML中的使用

 

XPath 语法: http://www.w3school.com.cn/xpath/xpath_syntax.asp

 

XPath (红色字体) 示例:

/bib/book/year
Result: <year> 1995 </year>
        <year> 1998 </year>

/bib/paper/year Result: empty

XPath: Restricted Kleene Closure 暴力查找node的感觉

//author
Result: <author> Serge Abiteboul </author>
        <author> <first-name> Rick </first-name>
                  <last-name> Hull </last-name>
        </author>
        <author> Victor Vianu </author>
        <author> Jeffrey D. Ullman </author>

/bib//first-name Result: <first-name> Rick </first-name>

XPath: Text Nodes 提取 (无子结构的) elem

/bib/book/author/text()
Result: Serge Abiteboul
        Victor Vianu
        Jeffrey D. Ullman

XPath: Text Nodes 提取 (有子结构的) elem

//author/*
Result: <first-name> Rick </first-name>
         <last-name> Hull </last-name>

XPath: Attribute Nodes 提取属性的内容

/bib/book/@price
Result: “55”

XPath: Qualifiers 只要有firstname子节点的元素

/bib/book/author[firstname]
Result: <author> <first-name> Rick </first-name>
                  <last-name> Hull </last-name>
        </author>

XPath: Qualifiers 只要条件为:有firstname子节点和address子节点,且address中下的某一level中有zip节点,以及下一level就得有city。满足如此条件的author下的lastname的内容。

/bib/book/author[firstname][address[//zip][city]]/lastname
Result: <lastname> ... </lastname>
        <lastname> ... </lastname>

XPath: 子节点的属性满足指定条件

/bib/book[@price < “60”]
/bib/book[author/@age < “25”]

XPath: author下的elem只允许有txt。

/bib/book[author/text()]

  

XPath 轴轴可定义相对于当前节点的节点集

轴可定义相对于当前节点的节点集。

轴名称结果
ancestor 选取当前节点的所有先辈(父、祖父等)。
ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
attribute 选取当前节点的所有属性。
child 选取当前节点的所有子元素。
descendant 选取当前节点的所有后代元素(子、孙等)。
descendant-or-self 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following 选取文档中当前节点的结束标签之后的所有节点。
namespace 选取当前节点的所有命名空间节点。
parent 选取当前节点的父节点。
preceding 选取文档中当前节点的开始标签之前的所有节点。
preceding-sibling 选取当前节点之前的所有同级节点。
self 选取当前节点。

 


 

XPath Containment

Return Node: [[name]] 使用double circles表示。

任意深度子目录存在:双斜线。

 

表达式解释:

root下的任意未知结点person,满足孩子中有name,任意子孙中需有属性zip = "12345"的结点。

满足以上条件,则返回这个person的phone。

 

 

Equivalence, Containment 

    • E = E’ if they return the same result
    • E ⊆ E’ if the result returned by E is a subset of that returned by E’.

 

返回的结果总是一致的,我们认为这是一个query

 

这个比较复杂,所以我们引入一种方法来解决:

Practical Algorithm for Linear XPath *,//

关键在于找到mapping。

 

第一个例子:

 

 第二个例子:

 

第三个例子:

为何不等价?

应该是前者包含后者!

注意1/*// 转化为双线。

注意2//name 这里没有*,所以是>=0,这导致了两者不等价!

 

 

Branching XPath *,//

  -- 难度加大,计算量大

视情况而定,此处略。

 


 

Distributed Query Evaluation

a.b*.c    // any num of b, here we regard it as a Query.

a.b+.c    // at least one num of b

Review 正则表达式 与 DFA 的关系

在分布式环境下的Query,如下:(如用在下图中查询这个Query)

 

 

A naïve approach takes too many communication steps

=> we have to do more work locally

A better approach needs to

1. identify all external references

2. identify targets of external references

 

Algorithm:

1. Given a query, we compute its automaton 计算出某一个query的对应的一个东西
2. Send it to each site 将这个东西分发给各个site
3. Start an identical process at each site 各个site分别处理这个东西
4. Compute two sets Stop(n, s) and Result(n, s) 计算出这两个结果
5. Transmits the relations to a central location and get their union 合并所有结果

 

Detail:

每个site都会有自己的一个《进出表》,如下:

Site 1:

In x1, x4
Out y1, y3

 

Site 2:

In y1, y3
Out z2

 

Site 3:

In z2
Out x4

 

相对于Query: a.b+.c 

Site 2 为例,该site将处理query并得到如下两个table:

 

《搞不定表》- Stop Table

Start End
(y1, s2) (z2, s2)
(y3, s2) (z2, s2)

这里的z2怎么得来?Site 2虽然不晓得其他site的信息,但起码知道

与自己有直接连接的node信息。比如:

与y3直接相连接的z2有可能作为s2

《能搞定表》- Result Table

Start End
(y1, s2) (y3, s3)
(y1, s3) (y1, s3)
(y3, s3) (y3, s3)

 

然后,每个site都应该返回了针对该query的俩表。

接下来就是如何合并这么些个表的问题。

让我们将整个表都列出来,做一次傻瓜式的demo。

Union:

Start Stop   Start Result  
(x1, s1) (y1, s2) stop1 (x1, s3) x1 result1
(x4, s2) (y3, s3) stop2  (x4, s2) x3 result2 
(y1, s2) (z2, s2) stop3  (x4, s3) x4 result3 
(y3, s2) (z2, s2) stop4  (y1, s2) y3 result4 
(z2, s2) (x4, s2) stop5  (y1, s3) y1 result5 
      (y3, s3) y3 result6 
      (z2, s1) z3 result7 
      (z2, s2) z2 result8 
      (z2, s3) z2 result9 

解说:

root    
stop1 在其他site能直接终止么?  
result4 还真有,可以直接结束 匹配到了(y1,s2)
stop3 不结束,绕一绕,其他site或许能给出新的sol 匹配到了(y1,s2)
result8 确实有,可以直接结束 匹配到了(z2,s2)
stop5 不结束,绕一绕,其他site或许能给出新的sol 匹配到了(z2,s2)
result2 还真有,可以直接结束 匹配到了(x4,s2)
stop2 不结束,绕一绕,其他site或许能给出新的sol 匹配到了(x4,s2)
result6 有的啦,可以直接结束  
n/a 不结束,绕一绕,其他site或许能给出新的sol 匹配不到了!

Answer:

{y3, z2, x3}

 


 

Regular Expression (正则表达式)

定义:

This definition may seem circular, but 1-3 form the basis
Precedence: Parentheses have the highest precedence,
followed by *, concatenation, and then union.

 

RE Examples (表达形式 = 实际的集合形式)

  -- 当search时希望return results in this kind of pattern.

• L(001) = {001}
• L(0+10*) = { 0, 1, 10, 100, 1000, 10000, … }  // union: or; * any number of 0
• L(0*10*) = {1, 01, 10, 010, 0010, …} i.e. {w | w has exactly a single 1}
• L( |- |- )* = {w | w is a string of even length}
• L((0(0+1))*) = { ε, 00, 01, 0000, 0001, 0100, 0101, …}
• L((0+ε)(1+ ε)) = {ε, 0, 1, 01}
• L(1Ø) = Ø ; concatenating the empty set to any set yields the empty set.
• Rε    = R  // ε就像1
• R+Ø = R  // 空集就像0

 

Exercise 1

∑ = {10, 11}, ∑* = {є, 10, 11, 1010, 1011, 1110, 1111, …}

表示集合里元素的数量各自都是任意的,然后组合在一起。

 

Exercise 2

L1 = {10, 1}, L2 = {011, 11}, L1L2 = {10011, 1011, 111}

哄小孩的题。

 

Exercise 3 

Write RE for
  – All strings of 0’s and 1’s (其实就是任意0与1的组合)

    • (0|1)*

  – All strings of 0’s and 1’s with at least 2 consecutive 0’s (需要至少有连续的0)

    • (0|1)*00(0|1)*

  – All strings of 0’s and 1’s beginning with 1 and not having two consecutive 0’s (不能有连续的0)

    • (1+10)*    // {1, 10} 其中的元素任意组合确实不会有连续的0出现,技巧哉!

 

More exercises

1) (0|1)*011
  • Answer: all strings of 0’s and 1’s ending in 011
2) 0*1*2*
  • Answer: any number of 0’s followed by any number of 1’s followed by any number of 2’s
3) 00*11*22*
  • Answer: strings in 0*1*2 with at least one of each symbo

 

 

Link: 百度百科

起源:

正则表达式的“鼻祖”或许可一直追溯到科学家对人类神经系统工作原理的早期研究。美国新泽西州的Warren McCulloch和出生在美国底特律的Walter Pitts这两位神经生理方面的科学家,研究出了一种用数学方式来描述神经网络的新方法,他们创造性地将神经系统中的神经元描述成了小而简单的自动控制元,从而作出了一项伟大的工作革新。
在1951 年,一位名叫Stephen Kleene的数学科学家,他在Warren McCulloch和Walter Pitts早期工作的基础之上,发表了一篇题目是《神经网事件的表示法》的论文,利用称之为正则集合的数学符号来描述此模型,引入了正则表达式的概念。正则表达式被作为用来描述其称之为“正则集的代数”的一种表达式,因而采用了“正则表达式”这个术语。
之后一段时间,人们发现可以将这一工作成果应用于其他方面。Ken Thompson就把这一成果应用于计算搜索算法的一些早期研究,Ken Thompson是 Unix的主要发明人,也就是大名鼎鼎的Unix之父。Unix之父将此符号系统引入编辑器QED,然后是Unix上的编辑器ed,并最终引入grep。Jeffrey Friedl 在其著作《Mastering Regular Expressions (2nd edition)》(中文版译作:精通正则表达式,已出到第三版)中对此作了进一步阐述讲解,如果你希望更多了解正则表达式理论和历史,推荐你看看这本书。
自此以后,正则表达式被广泛地应用到各种UNIX或类似于UNIX的工具中,如大家熟知的Perl。Perl的正则表达式源自于Henry Spencer编写的regex,之后已演化成了pcre(Perl兼容正则表达式Perl Compatible Regular Expressions),pcre是一个由Philip Hazel开发的、为很多现代工具所使用的库。正则表达式的第一个实用应用程序即为Unix中的 qed 编辑器。
然后,正则表达式在各种计算机语言或各种应用领域得到了广大的应用和发展,演变成为计算机技术森林中的一只形神美丽且声音动听的百灵鸟。
 
以上是关于正则表达式的起源和发展的历史描述,如今正则表达式在基于文本的编辑器和搜索工具中依然占据着一个非常重要的地位。
在最近的六十年中,正则表达式逐渐从模糊而深奥的数学概念,发展成为在计算机各类工具和软件包应用中的主要功能。不仅仅众多UNIX工具支持正则表达式,近二十年来,在WINDOWS的阵营下,正则表达式的思想和应用在大部分 Windows 开发者工具包中得到支持和嵌入应用!从正则式在Microsoft Visual Basic 6 或 Microsoft VBScript到.NET Framework中的探索和发展,WINDOWS系列产品对正则表达式的支持发展到无与伦比的高度,几乎所有 Microsoft 开发者和所有.NET语言都可以使用正则表达式。如果你是一位接触计算机语言的工作者,那么你会在主流操作系统(*nix[Linux, Unix等]、Windows、HP、BeOS等)、主流的开发语言(delphi、Scala、PHP、C#、Java、C++、Objective-c、Swift、VB、Javascript、Ruby以及Python等)、数以亿万计的各种应用软件中,都可以看到正则表达式优美的舞姿。

 

引擎

正则引擎主要可以分为两大类:一种是DFA,一种是NFA。这两种引擎都有了很久的历史(至今二十多年),当中也由这两种引擎产生了很多变体!
于是POSIX的出台规避了不必要变体的继续产生。这样一来,主流的正则引擎又分为3类:
一、DFA
二、传统型NFA,
三、POSIX NFA。
 
DFA 引擎在线性时状态下执行,因为它们不要求回溯(并因此它们永远不测试相同的字符两次)。DFA 引擎还可以确保匹配最长的可能的字符串。但是,
因为 DFA 引擎只包含有限的状态,所以它不能匹配具有反向引用的模式;
因为它不构造显示扩展,所以它不可以捕获子表达式。
 
传统的 NFA 引擎运行所谓的“贪婪的”匹配回溯算法,以指定顺序测试正则表达式的所有可能的扩展并接受第一个匹配项。
因为传统的 NFA 构造正则表达式的特定扩展以获得成功的匹配,所以它可以捕获子表达式匹配和匹配的反向引用。
但是,因为传统的 NFA 回溯,所以它可以访问完全相同的状态多次(如果通过不同的路径到达该状态)。
因此,在最坏情况下,它的执行速度可能非常慢。因为传统的 NFA 接受它找到的第一个匹配,所以它还可能会导致其他(可能更长)匹配未被发现。
 
POSIX NFA 引擎与传统的 NFA 引擎类似,不同的一点在于:在它们可以确保已找到了可能的最长的匹配之前,它们将继续回溯。因此,POSIX NFA 引擎的速度慢于传统的 NFA 引擎;并且在使用 POSIX NFA 时,您恐怕不会愿意在更改回溯搜索的顺序的情况下来支持较短的匹配搜索,而非较长的匹配搜索。
 
使用DFA引擎的程序主要有:awk,egrep,flex,lex,MySQL,Procmail等;
使用传统型NFA引擎的程序主要有:GNU Emacs,Java,ergp,less,more,.NET语言,PCRE library,Perl,PHP,Python,Ruby,sed,vi;
使用POSIX NFA引擎的程序主要有:mawk,Mortice Kern Systems’ utilities,GNU Emacs(使用时可以明确指定);
也有使用DFA/NFA混合的引擎:GNU awk,GNU grep/egrep,Tcl。
 
AWK是一种优良的文本处理工具。它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言(其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母)的最大功能取决于一个人所拥有的知识。AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言:AWK 程序设计语言, 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
最简单地说, AWK 是一种用于处理文本的编程语言工具。AWK 在很多方面类似于 shell 编程语言,尽管 AWK 具有完全属于其本身的语法
 
举例简单说明NFA与DFA工作的区别:
比如有字符串 this is yansen’s blog,正则表达式为 /ya(msen|nsen|nsem)/ (不要在乎表达式怎么样,这里只是为了说明引擎间的工作区别)。
NFA工作方式如下,先在字符串中查找 y 然后匹配其后是否为 a ,
如果是,则继续,查找其后是否为 m
如果否,则匹配其后是否为 n (此时淘汰msen选择支)。
然后继续看其后是否依次为 s,e,接着测试是否为 n ,是 n 则匹配成功,不是则测试是否为 m 。
 
为什么是 m ?因为 NFA 工作方式是以正则表达式为标准,反复测试字符串,这样同样一个字符串有可能被反复测试了很多次!
 
而DFA则不是如此,DFA会从 this 中 t 开始依次查找 y,定位到 y ,已知其后为 a ,则查看表达式是否有 a ,此处正好有 a 。然后字符串 a 后为 n ,DFA依次测试表达式,此时 msen 不符合要求淘汰。
nsen 和 nsem 符合要求,然后DFA依次检查字符串,检测到sen 中的 n 时只有nsen 分支符合,则匹配成功!
 
由此可以看出来,两种引擎的工作方式完全不同,一个(NFA)以表达式为主导,一个(DFA)以文本为主导
一般而论,DFA引擎则搜索更快一些!但是NFA以表达式为主导,反而更容易操纵,因此一般程序员更偏爱NFA引擎! 两种引擎各有所长,而真正的引用则取决与你的需要以及所使用的语言!

 

这里只简单瞧瞧 DFA (Deterministic Finite Automata),"确定有限状态自动机"。

 

b*a*b*a*b* 有循环,可见是个环。

 

Duality: RE与DFA的等价性

 

局限性:

Which languages CANNOT be described by any RE?
• Set of all bit strings with equal number of 0s and 1s.  // 没有计数相关功能
• Set of all decimal strings that represent prime numbers. // 又不是人工智能,:p

 

ab*a

可见,b有环。

a(a|b)*a

可见,(a|b)有环。思考环的构造,如下:

 

 

DFA to RE: State Elimination

• Eliminates states of the automaton and replaces the edges with regular expressions that includes the behavior of the eliminated states.
• Eventually we get down to the situation with just a start and final node, and this is easy to express as a RE

 

We can describe this automaton as: (R | SU*T)*SU*

分析:

对于第一个node来说,有两条路径:

    1. R自循环
    2. SU*T绕一圈后再回来

然后考虑end node:也是两条路径:

    1. U自循环
    2. “SU*T绕一圈后再回来”+S

于是便构成了: (R | SU*T)*SU*

 

We can describe this automaton as simply R*

 

标准的elimination过程

Example One:

1) First convert the edges to RE’s.

注意:简化的过程中不要丢失信息

2) 有个环,精简它。

3) 3-->1-->2的过程不能丢失,所以保留"11"。 

Answer: (0+10)*11(0+1)* 

 

Example Two:

1) First convert the edges to RE’s.

注意:简化的过程中不要丢失信息

2) 有个环,精简它。

3) 1-->2-->3的过程不能丢失,所以保留"10*1"。 

注意:这里有两个end node

策略:关掉node 1,计算;再关掉node 2,计算。

关掉node 3:

0*

关掉node 1:

0*10*1(0|10*1)*

合并结果(或操作):

0* | 0*10*1(0|10*1)*

 

posted @ 2017-06-06 16:23  郝壹贰叁  阅读(469)  评论(0编辑  收藏  举报