XPath 语法

XPath 表达式的上下文

XPath 表达式的计算取决于运算表达式所针对的上下文。上下文包括计算表达式所针对的节点及其关联的环境,包括下列内容:

  • 上下文节点相对于同辈节点的位置(按文档顺序)。

  • 上下文的大小 — 即上下文节点的同辈节点数加 1。

  • 可以解析变量引用的变量绑定。

  • 函数库。

  • 表达式范围中的命名空间声明。

为了更好地评价上下文的概念,请考虑包含节点的树。向树根请求所有名为 X 的节点时,将返回一个结果集,而向树枝请求这些节点时,将返回不同的结果集。因此,表达式的结果取决于执行表达式所针对的上下文。

XPath 表达式可以在一个特定的上下文匹配特定的模式,返回结果,然后相对于所返回节点的上下文执行其他运算。这样,在整个文档树中进行搜索时,使用 XPath 表达式非常灵活。

基本 XPath 表达式

以下是基本的 XPath 表达式类型。每一类型都在下面进行了描述。

  • 当前上下文

  • 文档根

  • 根元素

  • 递归下降

  • 特定元素

示例

下面的示例显示一些基本的 XPath 表达式。通过将这些简单的表达式组合在一起,并使用各种 XPath 运算符和特殊字符,可以生成更复杂的表达式。

当前上下文

以句点和正斜杠 (./) 作为前缀的表达式明确使用当前上下文作为上下文。例如,以下表达式引用当前上下文中的所有 <author> 元素:

./author

注意,此表达式等效于以下表达式:

文档根

以正斜杠 (/) 为前缀的表达式使用文档树的根作为上下文。例如,以下表达式引用此文档根的 <bookstore> 元素:

/bookstore
根元素

使用正斜杠后接星号 (/*) 的表达式将使用根元素作为上下文。例如,以下表达式查找文档的根元素:

递归下降

使用双正斜杠 (//) 的表达式指示可以包括零个或多个层次结构级别的搜索。如果此运算符出现在模式的开头,上下文相对于文档的根。例如,以下表达式引用当前文档中任意位置的所有 <author> 元素:

//author

.// 前缀指示上下文从层次结构中当前上下文所指示的级别开始。

特定元素

以元素名开头的表达式引用特定元素的查询,从当前上下文节点开始。例如,以下表达式引用当前上下文节点中 <images> 元素内的 <background.jpg> 元素:

images/background.jpg

以下表达式引用当前上下文节点中 <bookstore> 元素内的 <book> 元素的集合:

bookstore/book

以下表达式引用当前上下文节点中的所有 <first.name> 元素:

first.name
注意

元素名可以包括句点字符 (.)。这些名称的用法与任何其他名称一样。

运算符和特殊字符

XPath 表达式是使用下表中所示的运算符和特殊字符构造的。

/

子运算符;选择左侧集合的直接子级。此路径运算符出现在模式开头时,表示应从根节点选择该子级。

//

递归下降;在任意深度搜索指定元素。此路径运算符出现在模式开头时,表示应从根节点递归下降。

.

指示当前上下文。

..

当前上下文节点的父级。

*

通配符;选择所有元素,与元素名无关。

@

属性;属性名的前缀。

@*

属性通配符;选择所有属性,与名称无关。

:

命名空间分隔符;将命名空间前缀与元素名或属性名分隔。

( )

为运算分组,明确设置优先级。

[ ]

应用筛选模式。

[ ]

下标运算符;用于在集合中编制索引。

+

执行加法。

-

执行减法。

div

根据 IEEE 754 执行浮点除法。

*

执行乘法。

mod

从截断除法返回余数。

此表不包括布尔运算符和集运算符,这两个运算符在布尔、比较和集表达式集运算中列出。

优先级顺序(从最高优先级到最低优先级)的定义如下表所示。

优先级 字符 用途

1

( )

分组

2

[ ]

筛选器

3

/ //

路径运算

分组运算符 () 仅适用于顶级路径表达式。例如,(//author/degree | //author/name) 是有效的分组运算,但 //author/(degree | name) 不是。

筛选模式运算符 ([]) 的优先级高于路径运算符(///)。例如,表达式 //comment()[3] 选择相对于文档中任意位置备注的父级索引等于 3 的所有备注。此表达式与表达式 (//comment())[3] 不同,后者选择相对于父级的所有备注集中的第三个备注。前一个表达式可以返回多个备注,后一个表达式只能返回一个备注。

这些运算符和特殊字符在本参考文档中详细说明。

特定类型的元素集合可以使用路径运算符(///)确定。这些运算符根据其参数的“左侧”集合进行选择,“右侧”集合表示要选择的元素。子运算符 (/) 从左侧集合的直接子级中选择,而子代运算符 (//) 从左侧集合的任意子代中选择。因此,// 可以作为一个或多个层次级别的替代。

注意,路径运算符在执行查询时更改上下文。通过将路径运算符连接在一起,用户可以遍历文档树。

表达式 引用

author/first-name

当前上下文节点的 <author> 元素中的所有 <first-name> 元素。

bookstore//title

<bookstore> 元素中更深的一级或多级(任意子代)的所有 <title> 元素。注意,此表达式与以下模式 bookstore/*/title 不同。

bookstore/*/title

属于 <bookstore> 元素的孙级的所有 <title> 元素。

bookstore//book/excerpt//emph

<book> 元素的 <excerpt> 子级中的任意位置和 <bookstore> 元素中的任意位置的所有 <emph> 元素:

.//title

当前上下文中更深的一级或多级的所有 <title> 元素。注意,本质上只有这种情况需要句点表示法。

通过使用通配符 (*) 集合,不使用元素名即可引用元素。* 集合引用作为当前上下文的子级的所有元素,与名称无关。

示例

表达式 引用

author/*

<author> 元素的所有元素子级。

book/*/last-name

所有作为 <book> 元素的孙级的 <last–name> 元素。

*/*

当前上下文的所有孙级元素。

my:book

my 命名空间中的 <book> 元素。

my:*

my 命名空间中的所有元素。

注意,不支持模式 *:book

XPath 使用 @ 符号表示属性名。属性和子元素应公平对待,两种类型之间的功能应尽可能相当。

注意

属性不能包含子元素,所以,如果对属性应用路径运算符,将出现语法错误。此外,不能对属性应用索引,因为根据定义,不为属性定义任何顺序。

 

示例

表达式 引用

@style

当前元素上下文的 style 属性。

price/@exchange

当前上下文中 <price> 元素的 exchange 属性。

book/@style

所有 <book> 元素的 style 属性。

注意,以下示例无效,因为属性不能包含任何子级。

price/@exchange/total

使用 @* 可以返回某个元素的所有属性。对于将属性作为记录中的字段的应用程序,此表达式可能非常有用。

示例

表达式 引用

@*

当前上下文节点的所有属性。

@my:*

my 命名空间中的所有属性。不包括 my 命名空间中的元素的未限定属性。

注意,不支持模式 @*:title

 

XPath 集合

XPath 查询返回的集合在定义的范围内保留文档顺序、层次结构和标识。也就是说,按照文档顺序返回元素集合,没有重复的元素。因为根据定义,属性不排序,所以,为特定元素返回的属性不进行明确地排序。

具有特定标记名的所有元素的集合使用标记名本身表示。限定方法可以通过使用句点和正斜杠 (./) 表明元素是从当前上下文中选择,但是默认情况下将使用当前上下文,不必明确说明。

表达式 引用

./first-name

所有 <first-name> 元素。注意,此表达式等效于后面的表达式。

first-name

所有 <first-name> 元素。

使用 XPath 表达式可以很容易在节点集中查询特定的节点。只需为索引序号加上方括号。序号从 1 开始(第一个元素是编号 1)。

方括号字符 ([]) 的优先级高于斜杠字符(///)。有关更多信息,请参见运算符和特殊字符

示例

表达式 引用

author[1]

第一个 <author> 元素。

author[first-name][3]

具有 <first-name> 子元素的第三个 <author> 元素。

注意,索引相对于筛选的节点集。例如,请考虑以下数据。

<x>
  <y/>
  <y/>
</x>
<x>
  <y/>
  <y/>
</x>

下表显示如何选择特定的 <x><y> 元素。

表达式 引用

x/y[1]

每个 <x> 中的第一个 <y>

(x/y)[1]

<x> 元素中整个 <y> 元素集的第一个 <y>

x[1]/y[1]

第一个 <x> 中的第一个 <y>

上面的示例简单地引用使用暗示默认值(例如 child:: 轴)的 XPath 集合。对于此轴,子节点集合按照前向文档顺序编制索引。

对于其他轴(例如 ancestor::),在 XPath 表达式中明确使用轴名。对于此轴,上级集合按照后向文档顺序编制索引。从上表中考虑此示例:

x/y[1]

此表达式等效于以下表达式:

x/child::y[1]

两个表达式均意味着“对每个 <x> 元素选择第一个名为 <y> 的子元素”。

下面的示例使用了相同的语法。

x/ancestor::y[1]

此示例意味着“对每个 <x> 元素选择第一个名为 <y> 的祖先元素(按照后向文档顺序)”。语法相同但是顺序相反。

last() 函数对集合中的最后一个元素返回 True。注意,last 相对于父节点。

示例

表达式 引用

book[last()]

最后一个 <book> 元素。

book/author[last()]

每个 <book> 元素中的最后一个 <author> 元素。

(book/author)[last()]

<book> 元素中整个 <author> 元素集的最后一个 <author> 元素。

为了清楚起见,或正常的优先级不足以表达某个运算,可以使用括号为集合运算符分组。分组运算符可以在任何筛选表达式(谓词)中使用,例如 author[(degree or award)and publication]。也可以在顶级步长表达式中使用,例如 (book|magazine)(author/degree | book/award)。不能应用于低级步长表达式。例如,author/(degree | award)无效。

示例

表达式 引用

(book/author)

属于当前上下文节点中任何 <book> 元素的子元素的所有 <author> 元素。

author[(degree or award) and publication]

至少包含一个 <degree><award> 元素以及至少包含一个 <publication> 元素的所有 <author> 元素。

 

筛选器和筛选模式

通过将筛选子句 [pattern] 添加到集合中,可以对任何集合应用约束和分支。筛选器类似于 SQL WHERE 子句。筛选器中包含的模式称为“筛选模式”。筛选模式计算为布尔值,对集合中的每个元素进行测试。集合中所有未通过筛选模式测试的元素将从结果集合中省略。

为了方便起见,如果集合在筛选器内,若集合包含任何成员,则生成布尔值 TRUE,若集合为空,则生成 FALSE。author/degree 之类的表达式意味着,如果存在包含名为 <degree> 的子元素的 <author> 元素,集合到布尔值的转换函数将计算为 TRUE。

注意,在表达式的给定级别可以出现任意数目的筛选器。不允许使用空筛选器。

筛选器总是针对上下文进行计算。也就是说,表达式 book[author] 意味着,对每个找到的 <book> 元素测试是否包含 <author> 子元素。同样,book[author = 'Bob'] 意味着,对每个找到的 <book> 元素测试是否包含值为 Bob<author> 子元素。还可以使用句点 (.) 字符检查上下文的值。例如,book[. = 'Trenton'] 意味着,对当前上下文中找到的每一本书,测试值是否为 Trenton

表达式 引用

book[excerpt]

至少包含一个 <excerpt> 元素的所有 <book> 元素。

book[excerpt]/title

至少包含一个 <excerpt> 元素的 <book> 元素内的所有 <title> 元素。

book[excerpt]/author[degree]

至少包含一个 <degree> 元素并且在至少包含一个 <excerpt> 元素的 <book> 元素内的所有 <author> 元素。

book[author/degree]

至少包含一个 <author> 元素并且该元素至少包含一个 <degree> 子元素的 <book> 所有元素。

book[excerpt][title]

至少包含一个 <excerpt> 元素以及至少包含一个 <title> 元素的 <book> 所有元素。

布尔、比较和集表达式

筛选模式可以包含布尔表达式、比较表达式和集表达式。下表中列出的快捷方式表示此 XSL 转换 (XSLT) 实现中提供的备选符号。本文档讨论这些表达式运算符。

运算符 说明

and

逻辑与

or

逻辑或

not()

=

相等

!=

不相等

&lt; *

小于

&lt;= *

小于或等于

&gt; *

大于

&lt;= *

大于或等于

|

集运算;返回两个节点集的联合

* 扩展的 XPath 方法

万维网联合会 (W3C) 的运算符关键字语法使用空白和其他分隔符,不使用版本 2.5 中使用的美元字符 ($)。在 W3C 语法中,$xxx$ 格式的二进制关键字可以表示为 wsxxxws,其中 ws 是指标记终止符,可以是空白、单引号 (') 或双引号 (")。not() 等一元运算符使用函数表示法。尽管 Microsoft 实现支持这两种语法,但是,为了以后的兼容性,建议使用 W3C 语法。

比较运算符和布尔运算符的优先级顺序(从最高优先级到最低优先级)如下表所示。

1

( )

分组

2

[ ]

筛选

3

/

//

路径运算

4

< 或者 &lt;

<= 或者 &lt;=

> 或者 &gt;

>= 或者 &gt;=

比较

5

=

!=

比较

6

|

联合

7

not()

布尔值非

8

And

布尔值与

9

Or

布尔值或

在 XML 文档(例如 XSLT 样式表)中使用运算符时,<> 标记必须分别转义为 &lt;&gt;。例如,以下 XSLT 指令在所有 <price> 元素的数值小于或等于 10 的 <book> 元素上调用 XSLT 模板规则。

<xsl:apply-templates select="book[price &lt;= 10]"/>

XPath 表达式与 DOM 一起使用时,< 和 > 运算符不需要转义。例如,以下 JScript 语句选择所有 <price> 元素的数值小于或等于 10 的 <book> 元素。

var cheap_books = dom.selectNodes("book[price <= 10]");

布尔表达式可以匹配特定值的所有节点或包含特定范围的节点的所有节点。以下是返回 false 的布尔表达式的示例。

1 &gt;= 2

运算符区分大小写。

逻辑与和逻辑或

布尔运算符 andor 分别执行逻辑与和逻辑或运算。这些运算符与分组括号组合使用时,可以用于构建复杂的逻辑表达式。

示例

表达式 引用

author[degree and award]

至少包含一个 <degree> 元素以及至少包含一个 <award> 元素的所有 <author> 元素。

author[(degree or award) and publication]

至少包含一个 <degree><award> 元素以及至少包含一个 <publication> 元素的所有 <author> 元素。

布尔值非

not 布尔运算符在筛选模式中对表达式的值求非。

示例

表达式 引用

author[degree and not(publication)]

至少包含一个 <degree> 元素但是不包含 <publication> 元素的所有 <author> 元素

author[not(degree or award) and publication]

至少包含一个 <publication> 元素但是不包含任何 <degree> 元素或 <award> 元素的所有 <author> 元素。

示例

 

XML 文件 (test.xml)

<?xml version="1.0"?>
<test>

    <x a="1">
      <x a="2" b="B">
        <x>
          <y>y31</y>
          <y>y32</y>
        </x>
      </x>
    </x>

    <x a="2">
      <y>y2</y>
    </x>

    <x a="3">
      <y>y3</y>
    </x>

</test>

XSLT 文件 (test.xsl)

以下 XSLT 样式表选择所有没有任何属性的 <x> 元素。

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

<!-- suppress text nodes not covered in subsequent template rule -->
<xsl:template match="text()"/>

<xsl:template match="*">
   <xsl:element name="{name()}">
      <xsl:apply-templates select="*|@*"/>
      <xsl:if test="text()">
         <xsl:value-of select="."/>
      </xsl:if>
   </xsl:element>
</xsl:template>

<xsl:template match="@*">
   <xsl:attribute name="{name()}">
      <xsl:value-of select="."/>
   </xsl:attribute>
</xsl:template>

<xsl:template match="/test">
  <xsl:apply-templates select="//x[not(@*)] "/>
</xsl:template>

</xsl:stylesheet>

输出

应用于上述 XML 文件的转换将产生以下结果:

<x>
   <y>y31</y>
   <y>y32</y>
</x>
比较

要在 XPath 中比较两个对象,可以使用 = 测试是否相等,也可以使用 != 测试是否不相等。

对于比较运算,必须正好提供两个操作数。比较的过程是计算每个操作数,然后根据需要将操作数转换为相同的类型。按照下面的“比较的优先级顺序”中所述的过程完成比较。

所有元素和属性都是字符串,但是在进行数字比较时会自动被强制转换为整数值。在比较运算期间,文本数值会被强制转换为 long 或 double 类型,如下表所示。

有关 &lt; 和其他二进制比较运算符的信息,请参见下面的“二进制比较运算符”。

文本类型 比较 示例

String

text(lvalue) op text(rvalue)

a &lt; GGG

Integer

(long) lvalue op (long) rvalue

a &lt; 3

Real

(double) lvalue op (double) rvalue

a &lt; 3.1

单引号或双引号可以作为表达式中字符串的分隔符。这样更容易从脚本语言内部构造和传递模式。

有关如何使用 XPath 执行比较的更多信息,请参见 www.w3.org/TR/xpath 上 XML Path Language (XPath) Version 1.0 (W3C Recommendation 16 November 1999) 的第 3.4 节“Booleans”(英文)。

示例

表达式 引用

author[last-name = "Bob"]

至少包含一个值为 Bob<last-name> 元素的所有 <author> 元素。

author[last-name[1] = "Bob"]

第一个 <last-name> 子元素的值为 Bob 的所有 <author> 元素。

author/degree[@from != "Harvard"]

包含 from 属性不等于 "Harvard"<degree> 元素的所有 <author> 元素。

author[last-name = /editor/last-name]

包含与根元素下 <editor> 元素中的 <last-name> 元素相同的 <last-name> 元素的所有 <author> 元素。

author[. = "Matthew Bob"]

所有字符串值为 Matthew Bob<author> 元素。

比较的优先级顺序

与数据类型有关的比较遵循下列优先级顺序。

  • 如果至少有一个操作数为布尔值,每个操作数必须先转换为布尔值。

  • 否则,如果至少有一个操作数为数字,每个操作数必须先转换为数字。

  • 否则,如果至少有一个操作数为日期,每个操作数必须先转换为日期。

  • 否则,两个操作数都先转换为字符串。

二进制比较运算符

可以通过一组二进制比较运算符比较数字和字符串,然后返回布尔值结果。&lt;&lt;=&gt;&gt;= 运算符分别表示小于、小于等于、大于和大于等于。单引号或双引号可以作为表达式中字符串的分隔符。这样更容易从脚本语言内部构造和传递模式。

示例

表达式 引用

author[last-name = "Bob" and price &gt; 50]

包含值为 Bob<last-name> 元素以及值大于 50 的 <price> 元素的所有 <author> 元素。

degree[@from != "Harvard"]

from 属性不等于 "Harvard" 的所有 <degree> 元素。

author[last-name &gt;= "M"]

包含值以 M 或 M 以后的字母开头的 <last-name> 元素的所有 <author> 元素。

book[position() &lt;= 3]

XML 文件中的前三个 <book> 元素(1、2、3)。

示例

XML 文件 (test.xml)

<?xml version="1.0"?>
<test>

    <x a="1">
      <x a="2" b="B">
        <x>
          <y>y31</y>
          <y>y32</y>
        </x>
      </x>
    </x>

    <x a="2">
      <y>y2</y>
    </x>

    <x a="3">
      <y>y3</y>
    </x>

</test>

XSLT 文件 (test.xsl)

以下 XSLT 样式表选择所有按文档顺序处于同辈的第一位的 <x> 元素。

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

<!-- Suppress text nodes not covered in subsequent template rule. -->
<xsl:template match="text()"/>

<xsl:template match="*">
   <xsl:element name="{name()}">
      <xsl:apply-templates select="*|@*"/>
      <xsl:if test="text()">
         <xsl:value-of select="."/>
      </xsl:if>
   </xsl:element>
</xsl:template>

<xsl:template match="@*">
   <xsl:attribute name="{name()}">
      <xsl:value-of select="."/>
   </xsl:attribute>
</xsl:template>

<xsl:template match="/test">
  <xsl:apply-templates select="//x[position() = 1 ] "/>
</xsl:template>

</xsl:stylesheet>

格式化输出

应用于上述 XML 文件的转换将产生以下结果:

<x a="1">
  <x a="2" b="B">
     <x>
        <y>y31</y>
        <y>y32</y>
     </x>
   </x>
</x>
<x a="2" b="B">
   <x>
      <y>y31</y>
      <y>y32</y>
   </x>
</x>
<x>
   <y>y31</y>
   <y>y32</y>
</x>
集运算

XML 路径语言 (XPath) 支持集运算 |

Union (|) 运算符

|(即 union)运算符返回两个操作数的联合,操作数必须是节点集。例如,//author | //publisher 返回的节点集结合了所有 //author 节点和所有 //publisher 节点。多个 union 运算符可以链接在一起,组合多个节点集。例如,//author | //publisher | //editor | //book-seller 返回的节点集包含所有 //author//publisher//editor//book-seller elements。union 运算符保留文档顺序,并且不返回重复项。

示例

表达式 引用

first-name | last-name

包含当前上下文中的 <first-name><last-name> 元素的节点集。

(bookstore/book | bookstore/magazine)

包含 <bookstore> 元素中的 <book><magazine> 元素的节点集。

book | book/author

包含 <book> 元素中的所有 <book> 元素和所有 <author> 元素的节点集。

(book | magazine)/price

包含 <book><magazine> 元素的所有 <price> 元素的节点集。

示例

下面的示例说明 union 运算符的作用。

XML 文件 (test.xml)

<?xml version="1.0"?>
<test>
    <x a="1">
      <x a="2" b="B">
        <x>
          <y>y31</y>
          <y>y32</y>
        </x>
      </x>
    </x>
</test>

XSLT 文件 (test.xsl)

下面的 XSLT 样式页选择所有 a 属性等于 2<x> 元素以及没有属性的 <x> 元素。

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

   <!-- Suppress text nodes not covered in subsequent template rule. -->
   <xsl:template match="text()"/>

  <!-- Handles a generic element node. -->
   <xsl:template match="*">
      <xsl:element name="{name()}">
         <xsl:apply-templates select="*|@*" />
         <xsl:if test="text()">
            <xsl:value-of select="."/>
         </xsl:if>
      </xsl:element>
   </xsl:template>

   <!-- Handles a generic attribute node. -->
   <xsl:template match="@*">
      <xsl:attribute name="{name()}">
         <xsl:value-of select="."/>
      </xsl:attribute>
   </xsl:template>

   <xsl:template match="/test">
      <xsl:apply-templates select="//x[@a=2 | //x[not(@*)]/>
   </xsl:template>

</xsl:stylesheet>

转换产生以下结果:

<x a="2" b="B">
   <x>
      <y>31</y>
      <y>y32</y>
   </x>
</x>
<x>
   <y>y31</y>
   <y>y32</y>
</x>

优先级

布尔运算符和比较运算符之间的优先级顺序(从最高优先级到最低优先级)如下表所示。

1

( )

分组

2

[ ]

筛选

3

/

//

路径运算

4

&lt;

&lt;=

&gt;

&gt;=

比较

5

=

!=

比较

6

|

联合

7

not()

布尔值非

8

and

布尔值与

9

or

布尔值或

示例

下面的示例说明上面列出的运算符优先级的作用。

XML 文件 (test.xml)

<?xml version="1.0"?>
<test>

    <x a="1">
      <x a="2" b="B">
        <x>
          <y>y31</y>
          <y>y32</y>
        </x>
      </x>
    </x>

    <x a="1">
      <x a="2">
        <y>y21</y>
        <y>y22</y>
      </x>
    </x>

    <x a="1">
      <y>y11</y>
      <y>y12</y>
    </x>

    <x>
      <y>y03</y>
      <y>y04</y>
    </x>

</test>

基本 XSLT 文件 (test.xsl)

我们将使用这个基本 XSLT 文件作为后面一系列说明的基础。

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

   <!-- Suppress text nodes not covered in subsequent template rule. -->
   <xsl:template match="text()"/>

  <!-- Handles a generic element node. -->
   <xsl:template match="*">
      <xsl:element name="{name()}">
         <xsl:apply-templates select="*|@*" />
         <xsl:if test="text()">
            <xsl:value-of select="."/>
         </xsl:if>
      </xsl:element>
   </xsl:template>

   <!-- Handles a generic attribute node. -->
   <xsl:template match="@*">
      <xsl:attribute name="{name()}">
         <xsl:value-of select="."/>
      </xsl:attribute>
   </xsl:template>

</xsl:stylesheet>

情况 0:测试运行

可以在 XSLT 样式表中添加以下模板规则。

<xsl:template match="/test">
      <xsl:apply-templates select="*|@*/>
   </xsl:template>

这样将生成与原始文档相同的 XML 文档,不需要 <?xml version="1.0"?> 处理指令。

以下情况说明编写此模板规则的不同方式。重点是说明 XPath 运算符绑定到元素上的顺序。

情况 1:() 绑定得比 [] 紧密

以下模板规则从源文档的所有 <y> 元素中选择按文档顺序的第一个 <y> 元素。

<xsl:template match="/test">
      <xsl:apply-templates select="(//y)[1]"/>
   </xsl:template>

结果如下所示:

<y>y31</y>

情况 2:[] 绑定得比 / 或 // 紧密

以下模板规则选择所有在同辈之间处于第一位的 <y> 元素。

<xsl:template match="/test">
      <xsl:apply-templates select="//y[1]"/>
   </xsl:template>

结果如下所示:

<y>y31</y>

<y>y21</y>

<y>y11</y>

<y>y03</y>

情况 3:与、非

以下模板规则选择所有没有 <x> 子元素、具有 <x> 父元素以及没有任何属性的 <x> 元素。

<xsl:template match="/test">
   <xsl:apply-templates select=
    "//x[./ancestor::*[name()='x'] and *[name()!='x'] and not(@*)]"/>
</xsl:template>

结果是一个 <x> 元素,在下面列出其子元素:

<x>
   <y>y31</y>
   <y>y32</y>
</x>

情况 4:或、与、非

以下模板规则选择每个属于 <x> 元素的子元素的 <x> 元素或不属于 <x> 元素的父元素并且没有属性的 <x> 元素。

<xsl:template match="/test">
   <xsl:apply-templates select=
    "//x[./ancestor::*[name()='x'] or *[name()!='x'] and not(@*)]"/>
</xsl:template>

结果是包含下列 <x> 元素的节点集,在下面列出其子元素:

<x a="2" b="B">
  <x>
     <y>y31</y>
     <y>y32</y>
  </x>
</x>
<x>
  <y>y31</y>
  <y>y32</y>
</x>
<x a="2">
  <y>y21</y>
  <y>y22</y>
</x>
<x>
  <y>y03</y>
  <y>y04</y>
</x>

情况 5:与、或、非

以下模板规则选择每个属于 <x> 元素的子元素但不属于 <x> 元素的父元素的 <x> 元素或没有属性的 <x> 元素。

<xsl:template match="/test">
   <xsl:apply-templates select=
    "//x[./ancestor::*[name()='x'] and *[name()!='x'] or not(@*)]"/>
</xsl:template>

结果是包含下列 <x> 元素的节点集,在下面列出其子元素:

<x>
   <y>y31</y>
   <y>y32</y>
</x>
<x a="2">
  <y>y21</y>
  <y>y22</y>
</x>
<x>
  <y>y03</y>
  <y>y04</y>
</x>
位置路径

位置路径是一种 XPath 表达式,用于选择相对于上下文节点的一组节点。计算位置路径表达式所得到的节点集,将包含位置路径指定的节点。位置路径可以以递归方式包含表达式,用来筛选节点集。

在语法上,位置路径由一个或多个定位步骤组成,每个步骤通过正斜杠 (/) 分隔:

locationstep/locationstep/locationstep

每个定位步骤依次选择相对于上下文节点(即上一个定位步骤所选择的节点)的一组节点。通过这种方式表示的位置路径为相对位置路径。绝对位置路径从根元素开始:

/locationstep/locationstep/locationstep

在位置路径中,定位步骤从左到右进行计算。最左侧的定位步骤选择一组相对于上下文节点的节点。然后,这些节点成为上下文节点,用于处理下一个定位步骤。这种步骤的处理和上下文节点的更新自行重复,直到所有定位步骤处理完毕。

位置路径可以缩写,也可以不缩写。

在不缩写的位置路径中,定位步骤采用以下语法:

axis::node-test[predicate]

在此语法中,axis 指定定位步骤选择的节点与上下文节点的关系;node-test 指定定位步骤选择的节点的节点类型和扩展名称;predicate 是一个筛选表达式,进一步精确定位步骤中的节点选择。谓词是可选的。在此例中,定位步骤仅包含 axis::node-test。下表提供了一些示例。

不缩写的位置路径 说明
child::para[last()]

选择上下文节点的最后一个 <para> 元素。

parent::para

选择作为上下文节点父级的 <para> 元素。

child::text()

选择上下文节点的所有文本节点子级。

child::div/child::para

选择作为上下文节点子级的 <div> 元素的 <para> 子元素。

在缩写的位置路径中,轴指定符 axis:: 在定位步骤中未明确表达,而是通过一组快捷方式暗示。下表提供了一些示例。

缩写的位置路径 说明
para

选择上下文节点的 <para> 元素。

../para

选择作为上下文节点父级的 <para> 元素。

text()

选择上下文节点的所有文本节点子级。

./div/para

选择上下文节点的 <div> 元素子级的 <para> 元素子级。

下面总结了一些缩写:

不缩写 缩写
child::*

*

attribute::*

@*

/descendant-or-self::node()

//

self::node()

.

parent::node()

..

 

 

XPath 示例

本主题回顾整个 XPath 参考中出现的语法示例。所有示例均基于 XPath 语法的示例 XML 文件 (inventory.xml)。有关在测试文件中使用 XPath 表达式的示例,请参见本主题最后的“联合 ( | ) 示例”。

表达式 引用
./author

当前上下文中的所有 <author> 元素。注意,此表达式等效于下一行中的表达式。

author

当前上下文中的所有 <author> 元素。

first.name

当前上下文中的所有 <first.name> 元素。

/bookstore

本文档的文档元素 (<bookstore>)。

//author

文档中的所有 <author> 元素。

book[/bookstore/@specialty = @style]

style 属性值等于文档根目录的 <bookstore> 元素的 specialty 属性值的所有 <book> 元素。

author/first-name

属于 <author> 元素的子级的所有 <first-name> 元素。

bookstore//title

<bookstore> 元素中更深的一级或多级(任意子代)的所有 <title> 元素。注意,此表达式不同于下一行中的表达式。

bookstore/*/title

属于 <bookstore> 元素的孙级的所有 <title> 元素。

bookstore//book/excerpt//emph

<book> 元素的 <excerpt> 子级中的任意位置和 <bookstore> 元素中的任意位置的所有 <emph> 元素。

.//title

当前上下文中更深的一级或多级的所有 <title> 元素。注意,本质上只有这种情况需要句点表示法。

author/*

属于 <author> 元素的子级的所有元素。

book/*/last-name

属于 <book> 元素的孙级的所有 <last-name> 元素。

*/*

当前上下文的所有孙级元素。

*[@specialty]

具有 specialty 属性的所有元素。

@style

当前上下文的 style 属性。

price/@exchange

当前上下文中 <price> 元素的 exchange 属性。

price/@exchange/total

返回空节点集,因为属性不包含元素子级。XML 路径语言 (XPath) 语法允许使用此表达式,但是严格意义上讲无效。

book[@style]

当前上下文的具有 style 属性的所有 <book> 元素。

book/@style

当前上下文的所有 <book> 元素的 style 属性。

当前元素上下文的所有属性。

./first-name

当前上下文节点中的所有 <first-name> 元素。注意,此表达式等效于下一行中的表达式。

first-name

当前上下文节点中的所有 <first-name> 元素。

author[1]

当前上下文节点中的第一个 <author> 元素。

author[first-name][3]

具有 <first-name> 子级的第三个 <author> 元素。

my:book

my 命名空间中的 <book> 元素。

my:*

my 命名空间中的所有元素。

@my:*

my 命名空间中的所有属性(不包括 my 命名空间中的元素的未限定属性)。

注意,索引相对于父级。考虑以下数据:

<x>
  <y/>
  <y/>
</x>
<x>
  <y/>
  <y/>
</x>
表达式 引用
x/y[1]

每个 <x> 的第一个 <y> 子级。此表达式等效于下一行中的表达式。

x/y[position() = 1]

每个 <x> 的第一个 <y> 子级。

(x/y)[1]

<x> 元素的整个 <y> 子级元素集中的第一个 <y>

x[1]/y[2]

第一个 <x> 的第二个 <y> 子级。

其他示例引用 XPath 的示例 XML 文件。

表达式 引用

book[last()]

当前上下文节点的最后一个 <book> 元素。

book/author[last()]

当前上下文节点的每个 <book> 元素的最后一个 <author> 子级。

(book/author)[last()]

当前上下文节点的 <book> 元素的整个 <author> 子级元素集中的最后一个 <author> 元素。

book[excerpt]

至少包含一个 <excerpt> 元素子级的所有 <book> 元素。

book[excerpt]/title

属于 <book> 元素(也至少包含一个 <excerpt> 元素子级)的子级的所有 <title> 元素。

book[excerpt]/author[degree]

至少包含一个 <degree> 元素子级并且属于 <book> 元素(也至少包含一个 <excerpt> 元素)子级的所有 <author> 元素。

book[author/degree]

所有包含 <author> 子级的 <book> 元素,该子级至少包含一个 <degree> 子级。

author[degree][award]

至少包含一个 <degree> 元素子级以及至少包含一个 <award> 元素子级的所有 <author> 元素。

author[degree and award]

至少包含一个 <degree> 元素子级以及至少包含一个 <award> 元素子级的所有 <author> 元素。

author[(degree or award) and publication]

至少包含一个 <degree><award> 以及至少包含一个 <publication> 子级的所有 <author> 元素。

author[degree and not(publication)]

至少包含一个 <degree> 元素子级并且不包含 <publication> 元素子级的所有 <author> 元素。

author[not(degree or award) and publication]

至少包含一个 <publication> 元素子级并且不包含 <degree><award> 元素子级的所有 <author> 元素。

author[last-name = "Bob"]

至少包含一个值为 Bob<last-name> 元素子级的所有 <author> 元素。

author[last-name[1] = "Bob"]

第一个 <last-name> 子元素的值为 Bob 的所有 <author> 元素。注意,此表达式等效于下一行中的表达式。

author[last-name [position()=1]= "Bob"]

第一个 <last-name> 子元素的值为 Bob 的所有 <author> 元素。

degree[@from != "Harvard"]

from 属性不等于 "Harvard" 的所有 <degree> 元素。

author[. = "Matthew Bob"]

所有值为 Matthew Bob<author> 元素。

author[last-name = "Bob" and ../price &gt; 50]

包含值为 Bob<last-name> 子元素以及值大于 50 的 <price> 同辈元素的所有 <author> 元素。

book[position() &lt;= 3]

前三本书(1、2、3)。

author[not(last-name = "Bob")]

不包含值为 Bob<last-name> 子元素的所有 <author> 元素。

author[first-name = "Bob"]

至少包含一个值为 Bob<first-name> 元素的所有 <author> 元素。

author[* = "Bob"]

所有包含任何值为 Bob 的子元素的 author 元素。

author[last-name = "Bob" and first-name = "Joe"]

所有包含值为 Bob<last-name> 子元素和值为 Joe<first-name> 子元素的 <author> 元素。

price[@intl = "Canada"]

上下文节点中所有 intl 属性等于 "Canada"<price> 元素。

degree[position() &lt; 3]

属于上下文节点子级的前两个 <degree> 元素。

p/text()[2]

上下文节点中每个 <p> 元素的第二个文本节点。

ancestor::book[1]

与上下文节点最接近的 <book> 上级。

ancestor::book[author][1]

与上下文节点最接近的 <book> 上级,并且此 <book> 元素包含 <author> 元素子级。

ancestor::author[parent::book][1]

当前上下文中最接近的 <author> 上级,并且此 <author> 元素是 <book> 元素的子级。

为了演示 union 运算,我们使用以下 XPath 表达式:

x | y/x

在以下 XML 文件中选择所有值为 green 或 blue 的 <x> 元素:

XML 文件 (data1.xml)

<?xml version='1.0'?>
<?xml-stylesheet type="text/xsl" href="union.xsl"?>
<root>
   <x>green</x>
   <y>
      <x>blue</x>
      <x>blue</x>
   </y>
   <z>
      <x>red</x>
      <x>red</x>
   </z>
   <x>green</x>
</root>

XSLT 文件 (union.xsl)

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="root">
   <xsl:for-each select="x | y/x">
      <xsl:value-of select="."/>,
      <xsl:if test="not(position()=last())">,</xsl:if>
   </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

格式化输出

green,blue,blue,green

处理器输出

<?xml version="1.0" encoding="UTF-16"?>green,blue,blue,green

 

XPath 语法的示例 XML 文件 (inventory.xml)

XPath 参考文档中的某些主题使用该 XML 文件。该文件表示书店库存数据库的一个片断。

XML 文件 (inventory.xml)

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="myfile.xsl" ?>
<bookstore specialty="novel">
  <book style="autobiography">
    <author>
      <first-name>Joe</first-name>
      <last-name>Bob</last-name>
      <award>Trenton Literary Review Honorable Mention</award>
    </author>
    <price>12</price>
  </book>
  <book style="textbook">
    <author>
      <first-name>Mary</first-name>
      <last-name>Bob</last-name>
      <publication>Selected Short Stories of
        <first-name>Mary</first-name>
        <last-name>Bob</last-name>
      </publication>
    </author>
    <editor>
      <first-name>Britney</first-name>
      <last-name>Bob</last-name>
    </editor>
    <price>55</price>
  </book>
  <magazine style="glossy" frequency="monthly">
    <price>2.50</price>
    <subscription price="24" per="year"/>
  </magazine>
  <book style="novel" id="myfave">
    <author>
      <first-name>Toni</first-name>
      <last-name>Bob</last-name>
      <degree from="Trenton U">B.A.</degree>
      <degree from="Harvard">Ph.D.</degree>
      <award>Pulitzer</award>
      <publication>Still in Trenton</publication>
      <publication>Trenton Forever</publication>
    </author>
    <price intl="Canada" exchange="0.7">6.50</price>
    <excerpt>
      <p>It was a dark and stormy night.</p>
      <p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p>
      <definition-list>
        <term>Trenton</term>
        <definition>misery</definition>
      </definition-list>
    </excerpt>
  </book>
  <my:book xmlns:my="uri:mynamespace" style="leather" price="29.50">
    <my:title>Who's Who in Trenton</my:title>
    <my:author>Robert Bob</my:author>
  </my:book>
</bookstore>
posted @ 2009-07-16 23:00 zengsiyu 阅读(...) 评论(...) 编辑 收藏