XML与XPath的小贴士

1. XML

基本规定

  • 任何开始的东西都必须由结束。
<aTag src="apic.png"></aTag>
  • 如果要省略结束标签,必须如下:
<aTag src="apic.png" />
  • 开始和结束标签必须严格匹配。XML是区分大小写的

XML规范继承了SGML的DTD(Document Type Definition)。W3C还定义了另外一个叫schema的规范,用来实现和DTD类似的功能。

重要术语

  • 良构(well-formed)
    XML能够符合所有的语法约束。
  • 有效(valid)
    XML能够满足比如DTD之类的数据定义。有效的XML一定是良构的,反之不然。很多XML没有相应的DTD或者schema,但这种XML往往又能被解析,而它不能算是有效的。
  • 属性
    在起始标签中的描述信息。
  • CDATA(Character Data)
    一般指那些没有标记(比如标签)的数据。也可以指CDATA段落,它使得XML解析器在这里关闭标记识别功能。
  • PCDATA(Parsed Character Data)
    Parsed意味着XML解析器会对段落中的<和&标记进行处理。它可以被理解为是CDATA数据再加上少数几个标记。

其他注意点

  • 特殊字符
    有些特殊的字符是不能在XML文件中直接使用的,必须使用entity(实体)的形式来间接表达,和HTML一样。
特殊字符实体形式
<&lt;
>&gt;
&&amp;
&apos;
"&quot;
  • UTF-8编码
    需提前声明
<?xml version="1.0" encoding="UTF-8"?>
  • XSLT
    用来把XML翻译成其他格式,比如HTML。
  • XPath
    一种用来筛选XML文档内容的规范。
  • SOAP/XML-RPC
    用来与远程服务进行XML信息交换。
  • 名称空间
    XML名称空间是确保文档中元素唯一且能相互区分的方法。
<red xmlns="http://colors.beeworkshop.com/my">...</red>
定义名称空间后文档中的元素将与此名称空间所表示的URI相关联。

注意:名称空间中的URI只是一种表示唯一标识的方式,以URI形式表示的名称空间不会有重复。该起唯一标识作用的URI不一定是真实可以访问的网址,解析器也永远不会建立连接来请求此页面资源。
对于同一个元素,可以定义多个名称空间,形式上每个名称空间都要有一个前缀字符串用于标识区分。

<juicebox xmlns:color="http://colors.beeworkshop.com/chart"
		  xmlns:fruit="http://fruits.beeworkshop.com/fruitlst">
	<color:orange>#dd3e00</color:orange>
	<fruit:orange>Citrus sinensis</fruit:orange>
</juicebox>

上边定义了两个名称空间,分别用前缀color和fruit表示。

2. XPath

XPath是一门独立的语言,是W3C的规范。用来定义如何从XML文档中取出感兴趣的数据。有专门的XPath解析器以提供功能上的支持。XPath如果定位路径有问题,程序不会停下来报错,只是不返回任何值。XPath可以用于XML,也可以用于HTML。
教程可参考 https://www.w3school.com.cn/xpath/index.asp
当然XML及XPath都包含在了libxml2库中。
XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。

  • 基本概念
    将XML文档的组织理解为LInux的目录树结构。XPath使用了定位路径(location path)的概念来描述通往文档中某个/某些节点的寻址方式。定位路径可以从树的顶端开始,称为绝对路径;也可以从树的某个位置开始,称为相对路径。
    这里用/定义为根节点,把.定义为当前节点(上下文节点),而..定义为上下文节点的父节点。这类似于在Linux文件系统中定位文件。
  • 如何得到属性
    可以在属性名前加上@
/network/desc/@name可以得到下边的“a name”

<network>
	<desc name="a name">a comment</desc>
</network>
  • 如何得到元素文本节点内容
    可以在定位路径的末尾加上text()
/network/desc/text()可以得到下边的“a comment”

<network>
	<desc name="a name">a comment</desc>
</network>
  • 通配符的使用
/network/host/*/arec/text()
用来定位所有在<host></host>节点下带有<arec></arec>子节点的元素节点,并返回<arec></arec>标签中元素的内容。

/network/host/@*
能返回所有<host></host>元素的属性。

注:*可以用来匹配所有元素节点;而node()可以用来匹配所有节点(元素或者其他对象)。

  • 搜索子树的所有匹配
    在定位路径的任何位置使用//就意味着从树的那个位置开始一直往下找,返回所有匹配的结果。
/network//arec/text()
从<network></network>节点开始往下找,找出所有<arec></arec>标签中的文本。
  • 谓词(Predicates)
    谓词可以让我们能够从所有可选的节点中筛选出感兴趣的。谓词使用[ ]来完成选择。在定位路径中的任何位置都可以使用谓词。具体使用类似数组下标。
/network/host[2]/interface/arec/text()
请选择host的第二个分支,谢谢。数字索引从1开始。

/network/host[@name="babykeeper"]
筛选出父节点network下属性name的值为babykeeper的<host></host>

谓词也可以在路径中间使用
/network/host[@os="linux"]/service/../@name
上边的含义为,查找<network></network>节点下的<host></host>子节点,要求host节点的os属性值为linux,然后搜索抵达<service></service>节点。然后通过../@name来取得父节点的name属性,即当前节点<service></service>的父节点<host></host>的name属性值。达到的效果是取得那些有service子节点的host节点的名字。

//host/service[text()='DNS']
从根开始查找所有包含<service></service>节点的<host></host>节点,要求service节点的文本内容是DNS,即形如
...
	<host>
		<service>DNS</service>
	</host>
...
上述XPath也可简化为
//host/service[.='DNS']

//host/service[starts-with(normalize-space(.),'HTTP')]
谓词限定,首先对service节点的内容取消前后空格,然后看是否以HTTP开头。
  • 简写与轴
/child::network/child::host[postition()=2]/child::service[postition()=1]/child::text()
这里child::就是轴,它指出了搜索移动的方向是向DOM树的叶子节点方向进行的。
简写如下
/network/host[2]/service[1]/text()
常用的坐标轴是
following-sibling::
它指示搜索从兄弟节点的同级方向进行。
3. XPath总结

XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。
可以使用的第三方工具:
Oxygen XML
OxygenXML工具界面

XML的例子

<?xml version="1.0" encoding="UTF-8"?>

<bookstore>

<book category="COOKING">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>

<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

<book category="WEB">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>

<book category="WEB">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
</book>

</bookstore>
  • 选取节点
    XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。
表达式描述
nodename选取此节点的所有子节点。
/从根节点选取。
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
·选取当前节点。
··选取当前节点的父节点。
@选取属性。

例子

路径表达式结果
bookstore选取 bookstore 元素的所有子节点。
/bookstore选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book选取属于 bookstore 的子元素的所有 book 元素。
//book选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang选取名为 lang 的所有属性。
  • 谓词(Predicates)
    谓词用来查找某个特定的节点或者包含某个指定的值的节点。
    谓词被嵌在方括号中。

例子

路径表达式结果
/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。
  • 使用通配符
通配符描述
*匹配任何元素节点。
@*匹配任何属性节点。
node()匹配任何类型的节点。

例子

路径表达式结果
/bookstore/*选取 bookstore 元素的所有子元素。
//*选取文档中的所有元素。
//title[@*]选取所有带有属性的 title 元素。
  • 选择多个路径
    通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

例子

路径表达式结果
//book/title │ //book/price选取 book 元素的所有 title 和 price 元素。
//title │ //price选取文档中的所有 title 和 price 元素。
/bookstore/book/title │ //price选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。
  • XPath轴
    轴可定义相对于当前节点的节点集。
轴名称结果
ancestor选取当前节点的所有先辈(父、祖父等)。
ancestor-or-self选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
attribute选取当前节点的所有属性。
child选取当前节点的所有子元素。
descendant选取当前节点的所有后代元素(子、孙等)。
descendant-or-self选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following选取文档中当前节点的结束标签之后的所有节点。
namespace选取当前节点的所有命名空间节点。
parent选取当前节点的父节点。
preceding选取文档中当前节点的开始标签之前的所有节点。
preceding-sibling选取当前节点之前的所有同级节点。
self选取当前节点。
  • 位置路径表达式
    位置路径可以是绝对的,也可以是相对的。

绝对路径起始于正斜杠( / ),而相对路径不会这样。在两种情况中,位置路径均包括一个或多个步,每个步均被斜杠分割:

绝对位置路径
/step/step/...
相对位置路径
step/step/...
步(step)包括:

轴(axis)
定义所选节点与当前节点之间的树关系。可以理解为坐标轴。

节点测试(node-test)
识别某个轴内部的节点

零个或者更多谓语(predicate)
更深入地提炼所选的节点集

步的语法:

轴名称::节点测试[谓语]

例子

例子结果
child::book选取所有属于当前节点的子元素的 book 节点。
attribute::lang选取当前节点的 lang 属性。
child::*选取当前节点的所有子元素。
attribute::*选取当前节点的所有属性。
child::text()选取当前节点的所有文本子节点。
child::node()选取当前节点的所有子节点。
descendant::book选取当前节点的所有 book 后代。
ancestor::book选择当前节点的所有 book 先辈。
ancestor-or-self::book选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点)
child::*/child::price选取当前节点的所有 price 孙节点。
  • XPath的运算符
运算符描述实例返回值
计算两个节点集//book│//cd返回所有拥有 book 和 cd 元素的节点集
+加法6 + 410
-减法6 - 42
*乘法6 * 424
div除法8 div 42
=等于price=9.80如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。
!=不等于price!=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
<小于price<9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
<=小于或等于price<=9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
>大于price>9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
>=大于或等于price>=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。
orprice=9.80 or price=9.70如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。
andprice>9.00 and price<9.90如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。
mod计算除法的余数5 mod 21
  • 常用XPath函数

~ 有关数值的函数

名称说明
number(arg)返回参数的数值。参数可以是布尔值、字符串或节点集。例子:number(‘100’),结果:100
abs(num)返回参数的绝对值。例子:abs(3.14),结果:3.14。例子:abs(-3.14),结果:3.14
ceiling(num)返回大于 num 参数的最小整数。例子:ceiling(3.14),结果:4
floor(num)返回不大于 num 参数的最大整数。例子:floor(3.14),结果:3
round(num)把 num 参数舍入为最接近的整数。例子:round(3.14),结果:3
round-half-to-even()例子:round-half-to-even(0.5),结果:0。例子:round-half-to-even(1.5),结果:2。例子:round-half-to-even(2.5),结果:2

~ 字符串函数

名称说明
string(arg)返回参数的字符串值。参数可以是数字、逻辑值或节点集。例子:string(314),结果:“314”
codepoints-to-string(int,int,…)根据代码点序列返回字符串。例子:codepoints-to-string(84, 104, 233, 114, 232, 115, 101),结果:‘Thérèse’
string-to-codepoints(string)根据字符串返回代码点序列。例子:string-to-codepoints(“Thérèse”),结果:84, 104, 233, 114, 232, 115, 101
codepoint-equal(comp1,comp2)根据 Unicode 代码点对照,如果 comp1 的值等于 comp2 的值,则返回 true。(http://www.w3.org/2005/02/xpath-functions/collation/codepoint),否则返回 false。
compare(comp1,comp2),compare(comp1,comp2,collation)如果 comp1 小于 comp2,则返回 -1。如果 comp1 等于 comp2,则返回 0。如果 comp1 大于 comp2,则返回 1。(根据所用的对照规则)。例子:compare(‘ghi’, ‘ghi’),结果:0
concat(string,string,…)返回字符串的拼接。例子:concat('XPath ','is ',‘FUN!’),结果:‘XPath is FUN!’
string-join((string,string,…),sep)使用 sep 参数作为分隔符,来返回 string 参数拼接后的字符串。例子:string-join((‘We’, ‘are’, ‘having’, ‘fun!’), ’ ‘),结果:’ We are having fun! ‘。例子:string-join((‘We’, ‘are’, ‘having’, ‘fun!’)),结果:‘Wearehavingfun!’,例子:string-join((), ‘sep’),结果:’’
substring(string,start,len),substring(string,start)返回从 start 位置开始的指定长度的子字符串。第一个字符的下标是 1。如果省略 len 参数,则返回从位置 start 到字符串末尾的子字符串。例子:substring(‘Beatles’,1,4),结果:‘Beat’。例子:substring(‘Beatles’,2),结果:‘eatles’
string-length(string),string-length()返回指定字符串的长度。如果没有 string 参数,则返回当前节点的字符串值的长度。例子:string-length(‘Beatles’),结果:7
normalize-space(string),normalize-space()删除指定字符串的开头和结尾的空白,并把内部的所有空白序列替换为一个,然后返回结果。如果没有 string 参数,则处理当前节点。例子:normalize-space(’ The XML '),结果:‘The XML’
normalize-unicode()执行 Unicode 规格化。
upper-case(string)把 string 参数转换为大写。例子:upper-case(‘The XML’),结果:‘THE XML’
lower-case(string)把 string 参数转换为小写。例子:lower-case(‘The XML’),结果:‘the xml’
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’
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”
contains(string1,string2)如果 string1 包含 string2,则返回 true,否则返回 false。例子:contains(‘XML’,‘XM’),结果:true
starts-with(string1,string2)如果 string1 以 string2 开始,则返回 true,否则返回 false。例子:starts-with(‘XML’,‘X’),结果:true
ends-with(string1,string2)如果 string1 以 string2 结尾,则返回 true,否则返回 false。例子:ends-with(‘XML’,‘X’),结果:false
substring-before(string1,string2)返回 string2 在 string1 中出现之前的子字符串。例子:substring-before(‘12/10’,’/’),结果:‘12’
substring-after(string1,string2)返回 string2 在 string1 中出现之后的子字符串。例子:substring-after(‘12/10’,’/’),结果:‘10’
matches(string,pattern)如果 string 参数匹配指定的模式,则返回 true,否则返回 false。例子:matches(“Merano”, “ran”),结果:true
replace(string,pattern,replace)把指定的模式替换为 replace 参数,并返回结果。例子:replace(“Bella Italia”, “l”, ""),结果:'Be**a Itaia’。例子:replace(“Bella Italia”, “l”, “”),结果:‘Bea Itaia’
tokenize(string,pattern)例子:tokenize(“XPath is fun”, “\s+”),结果:(“XPath”, “is”, “fun”)

~ 布尔值函数

名称说明
boolean(arg)返回数字、字符串或节点集的布尔值。
not(arg)首先通过 boolean() 函数把参数还原为一个布尔值。如果该布尔值为 false,则返回 true,否则返回 true。例子:not(true()),结果:false
true()返回布尔值 true。例子:true(),结果:true
false()返回布尔值 false。例子:false(),结果:false

~ 关于节点的函数

名称说明
name(),name(nodeset)返回当前节点的名称或指定节点集中的第一个节点。
local-name(),local-name(nodeset)返回当前节点的名称或指定节点集中的第一个节点 - 不带有命名空间前缀。
namespace-uri(),namespace-uri(nodeset)返回当前节点或指定节点集中第一个节点的命名空间 URI。
lang(lang)如果当前节点的语言匹配指定的语言,则返回 true。例子:Lang(“en”) is true for <p xml:lang="en">…</p>,例子:Lang(“de”) is false for <p xml:lang="en">…</p>
root(),root(node)返回当前节点或指定的节点所属的节点树的根节点。通常是文档节点。

~ 有关序列的函数

名称说明
index-of((item,item,…),searchitem)返回在项目序列中等于 searchitem 参数的位置。例子:index-of ((15, 40, 25, 40, 10), 40),结果:(2, 4)。例子:index-of ((“a”, “dog”, “and”, “a”, “duck”), “a”),Result (1, 4)。例子:index-of ((15, 40, 25, 40, 10), 18),结果:()
remove((item,item,…),position)返回由 item 参数构造的新序列 - 同时删除 position 参数指定的项目。例子:remove((“ab”, “cd”, “ef”), 0),结果:(“ab”, “cd”, “ef”)。例子:remove((“ab”, “cd”, “ef”), 1),结果:(“cd”, “ef”)。例子:remove((“ab”, “cd”, “ef”), 4),结果:(“ab”, “cd”, “ef”)
:empty(item,item,…)如果参数值是空序列,则返回 true,否则返回 false。例子:empty(remove((“ab”, “cd”), 1)),结果:false
exists(item,item,…)如果参数值不是空序列,则返回 true,否则返回 false。例子:exists(remove((“ab”), 1)),结果:false
distinct-values((item,item,…),collation)返回唯一不同的值。例子:distinct-values((1, 2, 3, 1, 2)),结果:(1, 2, 3)
insert-before((item,item,…),pos,inserts)返回由 item 参数构造的新序列 - 同时在 pos 参数指定位置插入 inserts 参数的值。例子:insert-before((“ab”, “cd”), 0, “gh”),结果:(“gh”, “ab”, “cd”)。例子:insert-before((“ab”, “cd”), 1, “gh”),结果:(“gh”, “ab”, “cd”)。例子:insert-before((“ab”, “cd”), 2, “gh”),结果:(“ab”, “gh”, “cd”)。例子:insert-before((“ab”, “cd”), 5, “gh”),结果:(“ab”, “cd”, “gh”)
reverse((item,item,…))返回指定的项目的颠倒顺序。例子:reverse((“ab”, “cd”, “ef”)),结果:(“ef”, “cd”, “ab”)。例子:reverse((“ab”)),结果:(“ab”)
subsequence((item,item,…),start,len)返回 start 参数指定的位置返回项目序列,序列的长度由 len 参数指定。第一个项目的位置是 1。例子:subsequence(($item1, $item2, i t e m 3 , . . . ) , 3 ) , 结 果 : ( item3,...), 3),结果:( item3,...),3)(item3, …)。例子:subsequence(($item1, $item2, i t e m 3 , . . . ) , 2 , 2 ) , 结 果 : ( item3, ...), 2, 2),结果:( item3,...),2,2)(item2, $item3)
unordered((item,item,…))依据实现决定的顺序来返回项目。
zero-or-one(item,item,…)如果参数包含零个或一个项目,则返回参数,否则生成错误。
one-or-more(item,item,…)如果参数包含一个或多个项目,则返回参数,否则生成错误。
exactly-one(item,item,…)如果参数包含一个项目,则返回参数,否则生成错误。
deep-equal(param1,param2,collation)如果 param1 和 param2 与彼此相等(deep-equal),则返回 true,否则返回 false。
count((item,item,…))返回节点的数量。
avg((arg,arg,…))返回参数值的平均数。 例子:avg((1,2,3)) 结果:2
max((arg,arg,…))返回大于其它参数的参数。 例子:max((1,2,3)) 结果:3 例子:max((‘a’, ‘k’)) 结果:‘k’
min((arg,arg,…))返回小于其它参数的参数。 例子:min((1,2,3)) 结果:1 例子:min((‘a’, ‘k’)) 结果:‘a’
sum(arg,arg,…)返回指定节点集中每个节点的数值的总和。
id((string,string,…),node)Returns a sequence of element nodes that have an ID value equal to the value of one or more of the values specified in the string argument
idref((string,string,…),node)Returns a sequence of element or attribute nodes that have an IDREF value equal to the value of one or more of the values specified in the string argument
doc(URI),doc-available(URI)如果 doc() 函数返回文档节点,则返回 true,否则返回 false。
collection(),collection(string)

~ 上下文函数

名称说明
position()返回当前正在被处理的节点的 index 位置。例子://book[position()<=3],结果:选择前三个 book 元素
last()返回在被处理的节点列表中的项目数目。例子://book[last()],结果:选择最后一个 book 元素
current-dateTime()返回当前的 dateTime(带有时区)。
current-date()返回当前的日期(带有时区)。
current-time()返回当前的时间(带有时区)。
implicit-timezone()返回隐式时区的值。
default-collation()返回默认对照的值。
static-base-uri()返回 base-uri 的值。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值