集运算

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

|

Union

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>