XPath 的工作方式
XPath 规范是各种规范的基础,其中包括 XSLT 和链接/寻址规范,例如XPointer
。因此,了解 XPath 是许多高级 XML 使用的基础。本节介绍了 XSLT 上下文中的 XPath。
XPath Expressions
通常,XPath 表达式指定一种 Pattern,该 Pattern 选择一组 XML 节点。然后,XSLT 模板在应用转换时会使用这些 Pattern。 (另一方面,XPointer
添加了用于定义“点”或“范围”的机制,以便可以使用 XPath 表达式进行寻址)。
XPath 表达式中的节点不仅指元素。除其他外,它们还引用文本和属性。实际上,XPath 规范定义了一个抽象文档模型,该模型定义了七种节点:
-
Root
-
Element
-
Text
-
Attribute
-
Comment
-
Processing instruction
-
Namespace
XML 数据的根元素由 element 节点建模。 XPath 根节点包含文档的根元素以及与文档有关的其他信息。
XSLT/XPath 数据模型
像文档对象模型(DOM)一样,XSLT/XPath 数据模型由包含各种节点的树组成。在任何给定的元素节点下,都有文本节点,属性节点,元素节点,注解 节点和处理指令节点。
在此抽象模型中,语法上的区别消失了,您将获得数据的标准化视图。例如,在文本节点中,无论是在 CDATA 节中定义文本还是包含实体引用都没有关系。文本节点将由归一化的数据组成,因为所有解析完成后就存在。因此,无论是否使用诸如\<
之类的实体引用或 CDATA 节将其包含在内,文本都将包含\<
字符。 (类似地,文本将包含&
字符,无论它是使用&
传递的还是位于 CDATA 部分中)。
在本节中,我们将主要处理元素节点和文本节点。有关其他寻址机制,请参见 XPath 规范。
模板和上下文
XSLT 模板是一组格式化指令,适用于 XPath 表达式选择的节点。在样式表中,XSLT 模板如下所示:
<xsl:template match="//LIST">
...
</xsl:template>
表达式//LIST
从 Importing 流中选择LIST
个节点的集合。模板中的其他说明告诉系统如何处理它们。
由这样的表达式选择的节点集定义了上下文,在该上下文中可以评估模板中的其他表达式。该上下文可以视为整个集合-例如,在确定其包含的节点数时。
上下文也可以视为集合中的单个成员,因为每个成员都是一个接一个地处理的。例如,在LIST
处理模板内,表达式@type
引用当前LIST
节点的 type 属性。 (类似地,表达式@\*
引用当前 LIST 元素的所有属性)。
基本 XPath 寻址
XML 文档是节点的树结构(分层)集合。与分层目录结构一样,指定指向分层结构中特定节点的路径很有用(因此,规范名称为 XPath)。实际上,目录路径的许多符号是完整保留的:
-
正斜杠(/)用作路径分隔符。
-
从文档根目录开始的绝对路径以/开头。
-
从给定位置开始的相对路径以其他任何内容开头。
-
Double 倍句点(..)表示当前节点的父节点。
-
单个句点(.)表示当前节点。
例如,在可扩展 HTML(XHTML)文档(看起来像 HTML 但根据 XML 规则格式正确的 XML 文档)中,路径/h1/h2/
表示h1
下的h2
元素。 (回想一下,在 XML 中,元素名称区分大小写,因此,这种规范在 XHTML 中比在纯 HTML 中更有效,因为 HTML 不区分大小写.)
在 Pattern 匹配规范(例如 XPath)中,规范/h1/h2
选择位于h1
元素下的所有h2
元素。要选择特定的h2
元素,请使用方括号\[\]
进行索引(与用于数组的方括号类似)。路径/h1\[4\]/h2\[5\]
因此将选择第四h1
元素下面的第五h2
元素。
注意- 在 XHTML 中,所有元素名称均为小写。这是 XML 文档相当普遍的约定。但是,大写名称在这样的教程中更容易阅读。因此,在 XSLT 类的其余部分中,所有 XML 元素名称都将大写。 (另一方面,属性名称将保持小写)。
XPath 表达式中指定的名称引用元素。例如,/h1/h2
中的h1
表示h1
元素。要引用属性,请在属性名称前加上@
符号。例如,@type
表示元素的 type 属性。例如,假设您有一个包含 LIST 元素的 XML 文档,则表达式LIST/@type
选择LIST
元素的 type 属性。
注意- 因为表达式不是以/
开头,所以引用指定相对于当前上下文的列表节点-恰好在文档中的任何位置。
基本 XPath 表达式
完整的 XPath 表达式都利用了 XPath 定义的通配符,运算符和函数。您将很快了解更多有关这些内容的信息。在这里,我们仅介绍几个最常见的 XPath 表达式。
表达式@type="unordered"
指定一个名为type
的属性,其值为unordered
。诸如LIST/@type
之类的表达式指定LIST
元素的 type 属性。
您可以将这两种表示法结合起来以得到一些有趣的东西。在 XPath 中,通常与索引相关联的方括号符号(\[\]
)被扩展以指定选择标准。因此,表达式LIST\[@type="unordered"\]
选择类型值无序的所有LIST
元素。
元素存在类似的表达。每个元素都有一个关联的字符串 值,该字符串 值是通过 String 联位于该元素下面的所有文本段而形成的。 (有关该过程如何工作的详细说明,请参见元素的字符串 值)。
假设您使用 XML 结构建模组织中正在发生的事情,该 XML 结构由具有项目名称的文本字符串 的PROJECT
元素和ACTIVITY
元素,用于列出相关人员的多个PERSON
元素以及(可选)用于记录相关人员的STATUS
元素组成项目状态。以下是使用扩展方括号表示法的其他示例:
-
/PROJECT\[\.="MyProject"\]
:选择一个名为"MyProject"
的PROJECT
。 -
/PROJECT\[STATUS\]
:选择所有具有STATUS
子元素的项目。 -
/PROJECT\[STATUS="Critical"\]
:选择所有具有STATUS
子元素且字符串 值Critical
的项目。
组合索引地址
XPath 规范定义了很多寻址机制,可以用许多不同的方式来组合它们。结果,XPath 为相对简单的规范提供了很多表达能力。本节说明了其他有趣的组合:
-
LIST\[@type="ordered"\]\[3\]
:选择类型ordered
的所有LIST
个元素,并返回第三个元素。 -
LIST\[3\]\[@type="ordered"\]
:选择第三个LIST
元素,但仅当其类型为ordered
时。
注意- 地址运算符的更多组合在XPath specification的 2.5 节中列出。可以说,这是规范中定义 XSLT 转换最有用的部分。
Wild Cards
根据定义,不合格的 XPath 表达式会选择一组与指定 Pattern 匹配的 XML 节点。例如,/HEAD
匹配所有顶级HEAD
条目,而/HEAD\[1\]
仅匹配第一个条目。 Table 4-1列出了可在 XPath 表达式中使用的通配符,以扩大 Pattern 匹配的范围。
表 4-1 XPath 通配符
Wild card | Meaning |
---|---|
\* | 匹配任何元素节点(不是属性或文本)。 |
node\(\) | 匹配任何种类的任何节点:元素节点,文本节点,属性节点,处理指令节点,名称空间节点或 注解 节点。 |
@\* | 匹配任何属性节点。 |
在项目数据库示例中,/\*/PERSON\[\.="Fred"\]
匹配任何名为 Fred 的PROJECT
或ACTIVITY
元素。
Extended-Path Addressing
到目前为止,您已经看到的所有 Pattern 都在层次结构中指定了确切数量的级别。例如,/HEAD
指定层次结构中第一级的任何HEAD
元素,而/\*/\*
指定层次结构中第二级的任何元素。要在层次结构中指定不确定的级别,请使用 Double 斜杠(//
)。例如,XPath 表达式//PARA
选择文档中所有可能位于任何段落元素的元素。
//
Pattern 也可以在路径中使用。因此,表达式/HEAD/LIST//PARA
表示从/ HEAD/LIST
开始的子树中的所有段落元素。
XPath 数据类型和运算符
XPath 表达式产生一组节点,一个字符串,一个布尔值(一个真/假值)或一个数字。 Table 4-2列出了可以在 Xpath 表达式中使用的运算符:
表 4-2 XPath 运算符
Operator | Meaning |
---|---|
\| | 另类。例如,PARA\|LIST 选择所有PARA 和LIST 元素。 |
or , and | 返回两个布尔值的或/和。 |
= , != | 布尔值,字符串 和数字等于或不等于。 |
\< , \> , \<= , \>= | 小于,大于,小于或等于,大于或等于数字。 |
+ , \- , \* , div , mod | 加,减,乘,浮点除法和模数(余数)操作(例如 6 mod 4 = 2)。 |
表达式可以放在括号中,因此您不必担心运算符的优先级。
注意- 运算符优先级是一个回答以下问题的术语:“如果指定 b * c,是(a b)* c 还是(b * c)?” (运算符的优先级与表中所示的优先级大致相同)。
元素的字符串 值
元素的字符串 值是所有后代文本节点的 String 联,无论深度如何。考虑以下混合内容的 XML 数据:
<PARA>This paragraph contains a <b>bold</b> word</PARA>
\<PARA\>
元素的字符串 值为 此段落包含粗体字 。特别要注意,\<B\>
是\<PARA\>
的子代,而文本bold
是\<B\>
的子代。
关键是节点的所有子级中的所有文本都将 String 联在一起形成字符串 值。
另外,值得理解的是,XPath 定义的抽象数据模型中的文本已完全规范化。因此,无论 XML 结构在CDATA
部分中包含实体引用<
还是\<
,元素的字符串 值都将包含\<
字符。因此,在使用 XSLT 样式表生成 HTML 或 XML 时,必须将\<
转换为<
或将其包含在CDATA
部分中。同样,出现的&
必须转换为&
。
XPath Functions
本节以 XPath 功能的概述结尾。您可以使用 XPath 函数来选择节点集合,就像使用元素规范一样,例如已经看到的那些。其他函数返回字符串,数字或布尔值。例如,表达式/PROJECT/text\(\)
获取PROJECT
个节点的字符串 值。
许多功能取决于当前环境。在前面的示例中,每次调用text\(\)
函数的上下文都是当前选定的PROJECT
节点。
XPath 函数很多-在这里无法详细描述。本节提供了简要列表,其中显示了可用的 XPath 函数以及它们的功能摘要。有关功能的更多信息,请参见XPath specification的第 4 节。
Node-Set Functions
许多 XPath 表达式选择一组节点。本质上,它们返回一个节点集。一个功能也可以做到这一点。 id\(\.\.\.\)
函数返回具有指定 ID 的节点。 (仅当文档具有 DTD 时元素才具有 ID,该 DTD 指定哪个属性具有 ID 类型)。
Positional Functions
这些函数返回基于位置的数值。
-
last\(\)
:返回最后一个元素的索引。例如,/HEAD\[last\(\)\]
选择最后一个HEAD
元素。 -
position\(\)
:返回索引位置。例如,/HEAD\[position\(\) \<= 5\]
选择前五个HEAD
元素。 -
count\(\.\.\.\)
:返回元素数。例如,/HEAD\[count\(HEAD\)=0\]
选择没有子标题的所有HEAD
元素。
String Functions
这些函数对字符串 进行操作或返回字符串。
-
concat\(string, string, \.\.\.\)
:连接字符串 值。 -
starts\-with\(string1, string2\)
:如果string1
以string2
开头,则返回 true。 -
contains\(string1, string2\)
:如果string1
包含string2
,则返回 true。 -
substring\-before\(string1, string2\)
:返回string2
出现之前的string1
的开头。 -
substring\-after\(string1, string2\)
:返回出现string2
后剩余的string1
。 -
substring\(string, idx\)
:从索引位置到末尾(第一个char
的索引= 1)返回子字符串。 -
substring\(string, idx, len\)
:从索引位置返回指定 Long 度的子字符串。 -
string\-length\(\)
:返回上下文节点的字符串 值的大小;上下文节点是当前选定的节点-由 XPath 表达式选择的节点,其中应用了string\-length\(\)
之类的功能。 -
string\-length\(string\)
:返回指定字符串 的大小。 -
normalize\-space\(\)
:返回当前节点的规范化字符串 值(无前导或尾随空格,以及将空格字符序列转换为单个空格)。 -
normalize\-space\(string\)
:返回指定字符串 的规范化字符串 值。 -
translate\(string1, string2, string3\)
:转换string1
,将string2
中出现的字符替换为string3
中的相应字符。
注意- XPath 定义了三种获取元素文本的方式:text\(\)
,string\(object\)
和表达式中的元素名称所隐含的字符串 值:/PROJECT\[PERSON="Fred"\]
。
Boolean Functions
这些函数对布尔值进行操作或返回布尔值。
-
not\(\.\.\.\)
:否定指定的布尔值。 -
true\(\)
:返回 true。 -
false\(\)
:返回 false。 -
lang\(string\)
:如果上下文节点的语言(由xml:Lang
属性指定)与指定语言相同(或其子语言),则返回 true;否则,返回 true。例如,\<PARA_xml:Lang="en"\>\.\.\.\</PARA\>
的 Lang(“ en”)为 true。
Numeric Functions
这些函数对数字进行运算或返回数值。
-
sum\(\.\.\.\)
:返回指定节点集中每个节点的数值之和。 -
floor\(N\)
:返回不大于 N 的最大整数。 -
ceiling\(N\)
:返回不小于 N 的最小整数。 -
round\(N\)
:返回最接近 N 的整数。
Conversion Functions
这些函数将一种数据类型转换为另一种数据类型。
-
string\(\.\.\.\)
:返回数字,布尔值或节点集的字符串 值。 -
boolean\(\.\.\.\)
:返回数字,字符串 或节点集的布尔值(非零数字,非空节点集和非空字符串 均为 true)。 -
number\(\.\.\.\)
:返回布尔值,字符串 或节点集的数值(true 为 1,false 为 0,包含数字的字符串 变为该数字,节点集的字符串 值转换为数字)。
Namespace Functions
这些功能使您可以确定节点的名称空间 Feature。
-
local\-name\(\)
:返回当前节点的名称,减去名称空间前缀。 -
local\-name\(\.\.\.\)
:返回指定节点集中第一个节点的名称,减去名称空间前缀。 -
namespace\-uri\(\)
:从当前节点返回名称空间 URI。 -
namespace\-uri\(\.\.\.\)
:从指定节点集中的第一个节点返回名称空间 URI。 -
name\(\)
:返回当前节点的 extensions 称(URI 加本地名称)。 -
name\(\.\.\.\)
:返回指定节点集中第一个节点的 extensions 称(URI 加本地名称)。
Summary
XPath 运算符,函数,通配符和节点寻址机制可以通过多种方式组合。到目前为止,您所进行的介绍应该为您指定任何特定 Object 所需的 Pattern 提供了一个很好的起点。