• XML学习笔记6——XPath语言


      在上一篇笔记的结尾,我们接触到了两个用于选择XML文档中特定范围的元素<selector>和<field>,这两个元素的取值都是XPath表达式,那么,什么是XPath呢?简单的说,XPath是用于在XML文档中查找信息的语言,可用来在XML文档中遍历元素和属性,很多XML的相关技术比如XSLT、XQuery、XPointer等都是构建于XPath的基础之上,在这一篇笔记中,就来学习一下XPath语言。

    1、相关术语

    (1)节点(Node):格式良好的XML文档都可以转换为一个树型结构,XPath中的节点也就是这个树型结构中的节点。概况起来,有如下所列的七种节点:

    节点类型 说明
    XML文档根节点 XML文档的根称为文档节点或根节点
    元素节点 一个元素的开始标签、结束标签,以及之间的全部内容整体称之为元素节点
    属性节点 元素的每个属性都构成一个属性节点,包括属性名称和属性值两个部分,属性节点必须依附于元素节点
    命名空间节点 XML文档中的xmlns:prefix属性称之为命名空间节点,注意和属性节点的区别
    文本节点 XML元素中间的字符数据,包括CDATA段中的字符数据
    注释节点 XML文档里<!--和-->包含的注释部分构成注释节点
    处理指令节点 XML文档的处理指令部分构成处理指令节点

    (2)基本值(也称为原子值,Atomic Value):专门用于表示简单的字面值,如整数值,字符串等。基本值可以当成没有父节点也没有子节点的节点。

    (3)项目(Item):一个项目代表一个基本值或一个节点。

    (4)节点集和序列(Sequence):XPath表达式可以表示多个节点,多个节点的组合在XPath1.0中称为节点集,而在XPath2.0中添加了一个序列的术语,即可以代表普通的项目,也可以代表节点集。

    (5)节点关系:

    节点关系 说明
    父节点Parent 每个元素或属性都有一个父节点
    子节点Children 元素节点可以有0个、1个或多个子节点
    兄弟节点Sibling 父节点相同的节点称之为兄弟节点
    祖先节点Ancestor 节点的父节点、父节点的父节点一直到根节点
    后代节点Descendant 节点的子节点,子节点的子节点......

    (6)相对路径和绝对路径:与操作系统中的路径类似,XPath中也有相对路径和绝对路径,绝对路径以斜线(/)开头,总是从根节点开始匹配,而相对路径则不会以斜线开头,从当前路径开始匹配。

    2、XPath语法

      XPath使用路径表达式来访问XML中的节点或节点集,每个XPath表达式总是由一个或多个步(step)组成的,多个步直接使用斜线分隔。在XPath中,步的语法格式如下:

    ::节点测试[限定谓语]

    也就是说,每个步都通过了3次筛选,第一次是使用“”选择节点方向,第二次使用“节点测试”选取在指定轴方向上的部分节点,第三次则是使用“限定谓语”来对选中的节点进一步过滤。

    (1)轴:在XPath中,有下面列表中的各种轴:

    简化写法说明
    ancestor   选取当前节点的所有先辈(父、祖父等)节点
    ancestor-or-self   选取当前节点的所有先辈(父、祖父等)节点以及当前节点本身
    attribute 选取当前节点的所有属性节点,如果当前节点不是元素节点,则attribute轴方向上的节点集为空
    child 省略不写  选取当前节点的所有子节点
    descendant //  选取当前节点的所有后代节点(子、孙等)
    descendant-or-self   选取当前节点的所有后代节点(子、孙等)以及当前节点本身
    following   选取文档中当前节点的结束标签之后的所有节点,不会包含当前节点的后代节点和属性节点
    following-sibling   选取文档中当前节点的结束标签之后的所有兄弟节点
    namespace   选取当前节点的所有命名空间节点,当前节点不是元素节点,则namespace轴方向上的节点集为空
    parent .. 选取当前节点的父节点
    preceding   选取文档中当前节点的开始标签之前的所有节点,不会包含当前节点的后代节点和属性节点
    preceding-sibling   选取文档中当前节点的开始标签之前的所有兄弟节点
    self . 选取当前节点

    (2)节点测试:节点测试用于从指定轴方向上选取所匹配的特定的节点,在XPath中,常用的节点测试语法如下表所示:

    节点测试 说明
    nodename

    从指定轴方向上选出具有nodename的节点

    如child::book选择当前节点的所有book子节点

       descendant::book选择当前节点的所有book后代节点(包括book子节点、孙子节点等)

    node() 选择指定轴匹配的所有类型的节点
    text()

    选择指定轴匹配的所有文本类型的节点

    如child::text()选择当前节点的所有文本子节点

      descendant::text()选择当前节点的所有文本后代节点(包括文本子节点、文本孙子节点等)

    comment() 选择指定轴匹配的所有注释节点
    processing-instruction 选择指定轴匹配的所有处理指令节点
    * 节点测试中的通配符,表示所有,也即不进行过滤

    (3)限定谓语:每个步中可以接受0个或多个限定谓语,用于进一步过滤所选取的节点集,限定谓语放在方括号中,通常限定谓语返回一个boolean值。看下面的一些例子:

    路径表达式结果
    /bookstore/book[1] 选取属于 bookstore  元素的子元素的第一个 book 元素。
    /bookstore/book[last()] 选取属于 bookstore  元素的子元素的最后一个 book 元素。
    /bookstore/book[last()-1] 选取属于 bookstore  元素的子元素的倒数第二个 book 元素。
    /bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
    //title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
    //title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
    /bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
    /bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

    3、运算符

      从上面的实例中可以看到,在限定谓语中,还可以使用运算符、表达式,还有很多内置的函数供使用。这一小节先看看XPath中支持的运算符:

    (1)算术运算符:加(+)、减(-)、乘(*)、除(div)、取模(mod)

      算术运算符非常简单,但是需要注意几点:

    A、因为减号实际上也就是中划线,而中划线在XML中是合法的标识符号,从而带来了歧义,于是XPath强制规定,使用减号的时候,需要前后各加一个空格。

    B、在XPath中,所有的数值都是64位的double类型,即便直接书写成0、100;另外,XPath还有几个特殊的数值:正无穷大、负无穷大、非数。

    C、在运算时,如果操作数不是数值类型,会自动转换,下面的比较运算符、逻辑运算符如果有必要也会发生相应的自动类型转换。

    (2)比较运算符:等于(=)、不等于(!=)、小于(<)、小于或等于(<=)、大于(>)、大于或等于(>=)

      需要注意的是,不像其它编程语言,这里表示相等只需要一个等于号。

    (3)逻辑运算符:与(and)、或(or)

    (4)集合运算符:并集(|)

    4、表达式

    (1)for表达式:用于循环访问序列中的每个项,并对每项进行一次计算,最后将每项计算得到的结果组合成序列后返回,语法格式如下:

    for $var in sequence return rtExpression

    实际上,这里的for更类似于js中的foreach。还可以使用下面的形式遍历多个序列:

    for $var1 in sequence1, $var2 in sequence2 return fn($var1,$var2)

    (2)if表达式:用于处理分支,根据不同条件得到不同的返回值,语法格式如下:

    if (condition1)
    then rtVal1
    [else if (condition2)
    then rtVal2
    ...]
    else
    otherVal

    (3)some表达式:迭代中只要有一项满足条件就返回true,否则返回false,语法格式如下:

    some $var in sequence satisfies condition

    (4)every表达式:迭代中只有有一项不满足条件就返回false,否则返回true,语法格式如下:

    every $var in sequence satisfies condition

    5、内置函数库

      在XPath中还有大量的内置函数,用于增强相关功能,这些内置函数可以参考:XPath函数。我在下面也抄录一份供参考:

    分类 函数 说明
    存取函数 fn:node-name(node) 返回参数节点的节点名称。
    fn:nilled(node) 返回是否拒绝参数节点的布尔值。
    fn:data(item.item,...) 接受项目序列,并返回原子值序列。
    • fn:base-uri()
    • fn:base-uri(node)
    返回当前节点或指定节点的 base-uri 属性的值。
    • fn:document-uri()
    • fn:document-uri(node)
    返回当前节点或指定节点的 document-uri 属性的值。
    错误和跟踪函数
    • fn:error()
    • fn:error(error)
    • fn:error(error,description)
    • fn:error(error,description,error-object)

    例子:error(fn:QName('http://example.com/test', 'err:toohigh'), 'Error: Price is too high')

    结果:向外部处理环境返回 http://example.com/test#toohigh 以及字符串 "Error: Price is too high"。

    fn:trace(value,label) 用于对查询进行 debug。
    数值函数 fn:number(arg)

    返回参数的数值。参数可以是布尔值、字符串或节点集。

    例子:number('100')

    结果:100

    fn:abs(num) 返回参数的绝对值。
    fn:ceiling(num) 返回大于或等于 num 参数的最小整数。
    fn:floor(num) 返回小于或等于 num 参数的最大整数。
    fn:round(num) 把 num 参数四舍五入为最接近的整数。
    fn:round-half-to-even()

    返回最接近参数num的偶数

    例子:round-half-to-even(0.5) 结果:0

    例子:round-half-to-even(1.5) 结果:2

    例子:round-half-to-even(2.5) 结果:2

    字符串函数 fn:string(arg) 返回参数的字符串值。参数可以是数字、逻辑值或节点集。 
    fn:codepoints-to-string(int,int,...)

    根据一个Unicode值序列序列返回字符串。

    例子:codepoints-to-string((84, 104, 233, 114, 232, 115, 101))

    结果:'Thérèse'

    注意:该函数的参数是一个Unicode值序列,因此必须用括号将参数括起来

    fn:string-to-codepoints(string) 根据字符串返回每个字符所对应的Unicode值的序列。
    fn:codepoint-equal(comp1,comp2) 根据 Unicode 值序列比较,如果 comp1 的值等于 comp2 的值,则返回 true,否则返回 false。 
    • fn:compare(comp1,comp2)
    • fn:compare(comp1,comp2,collation)

    根据对照规则,comp1小于comp2返回 -1;comp1等于comp2,返回0;comp1大于comp2返回1。

    fn:concat(string,string,...) 返回字符串的拼接。
    fn:string-join((string,string,...),sep) 使用 sep 参数作为分隔符,来返回 string 参数拼接后的字符串。
    • fn:substring(string,start,len)
    • fn:substring(string,start)

    返回从 start 位置开始的指定长度的子字符串。第一个字符的下标是 1。

    如果省略 len 参数,则返回从位置 start 到字符串末尾的子字符串。

    • fn:string-length(string)
    • fn:string-length()
    返回指定字符串的长度。如果没有 string 参数,则返回当前节点的字符串值的长度
    • fn:normalize-space(string)
    • fn:normalize-space()
    删除指定字符串的首尾空白,并把内部连续空白压缩为一个,然后返回结果。没有参数,则处理当前节点。 
    fn:normalize-unicode() 执行 Unicode 规格化。
    fn:upper-case(string)  把 string 参数转换为大写。
    fn:lower-case(string)  把 string 参数转换为小写。
    fn:translate(string1,string2,string3) 

    把 string1 中的 string2 替换为 string3。

    例子:translate('12:30','30','45')

    结果:'12:45'

    例子:translate('12:30','03','54')

    结果:'12:45'

    例子:translate('12:30','0123','abcd')

    结果:'bc:da'

    fn:escape-uri(stringURI,esc-res) 

    例子:escape-uri("http://example.com/test#car", true())

    结果:"http%3A%2F%2Fexample.com%2Ftest#car"

    例子:escape-uri("http://example.com/test#car", false())

    结果:http://example.com/test#car

    例子:escape-uri ("http://example.com/~bébé", false())

    结果:"http://example.com/~b%C3%A9b%C3%A9"

    fn:contains(string1,string2)  如果 string1 包含 string2,则返回 true,否则返回 false。
    fn:starts-with(string1,string2)  如果 string1 以 string2 开始,则返回 true,否则返回 false。
    fn:ends-with(string1,string2)  如果 string1 以 string2 结尾,则返回 true,否则返回 false。
    fn:substring-before(string1,string2)  返回 string2 在 string1 中出现之前的子字符串。
    fn:substring-after(string1,string2)  返回 string2 在 string1 中出现之后的子字符串。
    fn:matches(string,pattern)  如果 string 参数匹配指定的模式,则返回 true,否则返回 false。
    fn:replace(string,pattern,replace)  把指定的模式替换为 replace 参数,并返回结果。
    fn:tokenize(string,pattern)

    例子:tokenize("XPath is fun", "s+")

    结果:("XPath", "is", "fun")

    anyURI函数 fn:resolve-uri(relative,base)  
    逻辑函数 fn:boolean(arg)  返回数字、字符串或节点集的布尔值。
    fn:not(arg)  首先通过 boolean() 函数把参数还原为一个布尔值,然后再取反。 
    fn:true()  返回布尔值 true。 
    fn:false()  返回布尔值 false。 
    日期时间函数 fn:dateTime(date,time)  把参数转换为日期和时间。 
    fn:years-from-duration(datetimedur) 返回参数值的年份部分的整数,以标准词汇表示法来表示。 
    fn:months-from-duration(datetimedur)  返回参数值的月份部分的整数,以标准词汇表示法来表示。 
    fn:days-from-duration(datetimedur)  返回参数值的天部分的整数,以标准词汇表示法来表示。 
    fn:hours-from-duration(datetimedur)  返回参数值的小时部分的整数,以标准词汇表示法来表示。 
    fn:minutes-from-duration(datetimedur)  返回参数值的分钟部分的整数,以标准词汇表示法来表示。 
    fn:seconds-from-duration(datetimedur)  返回参数值的分钟部分的十进制数,以标准词汇表示法来表示。 
    fn:year-from-dateTime(datetime)  返回参数本地值的年部分的整数。 
    fn:month-from-dateTime(datetime)  返回参数本地值的月部分的整数。 
    fn:day-from-dateTime(datetime)  返回参数本地值的天部分的整数。 
    fn:hours-from-dateTime(datetime)  返回参数本地值的小时部分的整数。 
    fn:minutes-from-dateTime(datetime)  返回参数本地值的分钟部分的整数。 
    fn:seconds-from-dateTime(datetime)  返回参数本地值的秒部分的十进制数。 
    fn:timezone-from-dateTime(datetime)  返回参数的时区部分,如果存在。 
    fn:year-from-date(date)  返回参数本地值中表示年的整数。 
    fn:month-from-date(date)  返回参数本地值中表示月的整数。 
    fn:day-from-date(date) 返回参数本地值中表示天的整数。 
    fn:timezone-from-date(date)  返回参数的时区部分,如果存在。 
    fn:hours-from-time(time)  返回参数本地值中表示小时部分的整数。 
    fn:minutes-from-time(time) 返回参数本地值中表示分钟部分的整数。 
    fn:seconds-from-time(time)  返回参数本地值中表示秒部分的整数。 
    fn:timezone-from-time(time)  返回参数的时区部分,如果存在。 
    fn:adjust-dateTime-to-timezone(datetime,timezone)  如果 timezone 参数为空,则返回没有时区的 dateTime。否则返回带有时区的 dateTime。 
    fn:adjust-date-to-timezone(date,timezone) 如果 timezone 参数为空,则返回没有时区的 date。否则返回带有时区的 date。 
    fn:adjust-time-to-timezone(time,timezone) 如果 timezone 参数为空,则返回没有时区的 time。否则返回带有时区的 time。 
     QName相关函数  fn:QName()   
    fn:local-name-from-QName()  
    fn:namespace-uri-from-QName()   
    fn:namespace-uri-for-prefix()   
    fn:in-scope-prefixes()   
    fn:resolve-QName()   
    节点函数 
    •  
    • fn:name()
    • fn:name(nodeset)
    返回当前节点的名称或指定节点集中的第一个节点。 
    • fn:local-name()
    • fn:local-name(nodeset)
    返回当前节点的名称或指定节点集中的第一个节点 - 不带有命名空间前缀。 
    • fn:namespace-uri()
    • fn:namespace-uri(nodeset)
    返回当前节点或指定节点集中第一个节点的命名空间 URI。 
    fn:lang(lang) 

    如果当前节点的语言匹配指定的语言,则返回 true。

    例子:Lang("en") is true for <p xml:lang="en">...</p>

    例子:Lang("de") is false for <p xml:lang="en">...</p>

    • fn:root()
    • fn:root(node)
    返回当前节点或指定的节点所属的节点树的根节点。通常是文档节点。 
    上下文函数 fn:position() 

    返回当前正在被处理的节点的 index 位置。

    例子://book[position()<=3]

    结果:选择前三个 book 元素

    fn:last() 

    返回在被处理的节点列表中的项目数目。

    例子://book[last()]

    结果:选择最后一个 book 元素 

    fn:current-dateTime()  返回当前的 dateTime(带有时区)。 
    fn:current-date()  返回当前的日期(带有时区)。 
    fn:current-time()  返回当前的时间(带有时区)。 
    fn:implicit-timezone()  返回隐式时区的值。 
    fn:default-collation()  返回默认对照的值。
    fn:static-base-uri()  返回 base-uri 的值。 
    序列函数 一般序列函数 fn:index-of((item,item,...),searchitem) 

    返回在项目序列中等于 searchitem 参数的位置。

    例子:index-of ((15, 40, 25, 40, 10), 40)

    结果:(2, 4)

    fn:remove((item,item,...),position)  返回由 item 参数构造的新序列 - 同时删除 position 参数指定的项目。 
    fn:empty(item,item,...)  如果参数值是空序列,则返回 true,否则返回 false。 
    fn:exists(item,item,...)  如果参数值不是空序列,则返回 true,否则返回 false。 
    fn:distinct-values((item,item,...),collation) 

    返回唯一不同的值。

    例子:distinct-values((1, 2, 3, 1, 2))

    结果:(1, 2, 3) 

    fn:insert-before((item,item,...),pos,inserts)  返回由 item 参数构造的新序列 - 同时在 pos 参数指定位置插入 inserts 参数的值。 
    fn:reverse((item,item,...))  返回指定的项目的颠倒顺序。 
    fn:subsequence((item,item,...),start,len)  返回 start 参数指定的位置返回项目序列,序列的长度由 len 参数指定。第一个项目的位置是 1。 
    fn:unordered((item,item,...)) 依据实现决定的顺序来返回项目。 
    容量测试函数 fn:zero-or-one(item,item,...)  如果参数包含零个或一个项目,则返回参数,否则生成错误。 
    fn:one-or-more(item,item,...)  如果参数包含一个或多个项目,则返回参数,否则生成错误。 
    fn:exactly-one(item,item,...)  如果参数包含一个项目,则返回参数,否则生成错误。 
    比较函数 fn:deep-equal(param1,param2,collation) 如果 param1 和 param2 与彼此相等(deep-equal),则返回 true,否则返回 false。
    合计函数 fn:count((item,item,...))  返回节点的数量。 
    fn:avg((arg,arg,...)) 返回参数值的平均数。
    fn:max((arg,arg,...)) 返回参数中的最大值。
    fn:min((arg,arg,...)) 返回参数中的最小值。
    fn:sum(arg,arg,...) 返回指定节点集中每个节点的数值的总和。
    序列生成函数 fn:id((string,string,...),node)  
    fn:idref((string,string,...),node)  
    fn:data((item1,item2,...)) 返回item1、item2等各项的值所组成的序列。
    fn:doc(URI)  
    fn:doc-available(URI) 如果 doc() 函数返回文档节点,则返回 true,否则返回 false。
    • fn:collection()
    • fn:collection(string)
     

    很明显,把这些内置函数放在这里的目的并不是要强行记住,而只是需要的时候当字典查查(XQuery1.0和XPath共享了这些内置函数,有事没事看看,混个眼熟也挺好的)。

  • 相关阅读:
    pip 安装指定版本
    译文:A Robust and Modular Multi-Sensor Fusion ApproachApplied to MAV Navigation
    泡泡一分钟:Perception-aware Receding Horizon Navigation for MAVs
    泡泡一分钟: A Linear Least Square Initialization Method for 3D Pose Graph Optimization Problem
    泡泡一分钟:LandmarkBoost: Efficient Visual Context Classifiers for Robust Localization
    泡泡一分钟:Visual Odometry Using a Homography Formulation with Decoupled Rotation and Translation Estimation Using Minimal Solutions
    小程序在同一行
    oracle分页查询原理浅析
    css实现圆形头像
    纯css控制文字2行显示多余部分隐藏
  • 原文地址:https://www.cnblogs.com/linjisong/p/3307657.html
Copyright © 2020-2023  润新知