Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Set Operations

Set Operations

XML Path Language (XPath) supports the set operation |.

Union (|) Operator

The |, or union, operator returns the union of its two operands, which must be node-sets. For example, //author | //publisher returns a node-set that combines all the //author nodes and all the //publisher nodes. Multiple union operators can be chained together to combine multiple node-sets. For example, //author | //publisher | //editor | //book-seller returns a node-set containing all //author, //publisher, //editor, and //book-seller elements. The union operator preserves document order and does not return duplicates.

Examples

Expression Refers to

first-name | last-name

A node set containing <first-name> and <last-name> elements in the current context.

(bookstore/book | bookstore/magazine)

A node set containing <book> or <magazine> elements inside a <bookstore> element.

book | book/author

A node set containing all <book> elements and all <author> elements within <book> elements.

(book | magazine)/price

The node set containing all <price> elements of either <book> or <magazine> elements.

Example

The following example illustrates the effect of the union operator.

XML File (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 File (test.xsl)

The following XSLT style sheet selects all the <x> elements whose a attribute is equal to 2, plus those <x> elements that have no attributes.

<?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>

The transformation yields the following result:

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

Precedence

Precedence order (from highest precedence to lowest) between Boolean and comparison operators is shown in the following table.

Precedence Operators Description

1

( )

Grouping

2

[ ]

Filters

3

/

//

Path operations

4

&lt;

&lt;=

&gt;

&gt;=

Comparisons

5

=

!=

Comparisons

6

|

Union

7

not()

Boolean not

8

and

Boolean and

9

or

Boolean or

Example

The following example illustrates the effect of the operator precedence listed above.

XML File (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>

Basic XSLT File (test.xsl)

We will use this basic XSLT file as a starting point for the series of illustrations that follow.

<?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>

Case 0. Test run

You can add the following template-rule to the XSLT style sheet.

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

This will produce an XML document identical to the original one, without the <?xml version="1.0"?> processing instruction.

The following cases show different ways of writing this template rule. The point is to show the order in which the XPath operators bind to an element.

Case 1: () binds tighter than []

The following template rule selects the first <y> element in the document order, from all the <y> elements in the source document.

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

The result is as follows:

<y>y31</y>

Case 2: [] binds tighter than / or //

The following template rule selects all the <y> elements that are the first among their siblings.

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

The result is as follows:

<y>y31</y>

<y>y21</y>

<y>y11</y>

<y>y03</y>

Case 3: and, not

The following template rule selects all the <x> elements that have no <x> child elements, that have an <x> parent element, and that do not have any attributes.

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

The result is a single <x> element, listed below with its children:

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

Case 4: or, and, not

The following template rule selects each <x> elements that is a child of an <x> element; or, that is not a parent of an <x> element and has no attributes.

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

The result is a node set containing the following <x> elements, listed below with its children:

<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>

Case 5: and, or, not

The following template rule selects each <x> element that is a child of an <x> element but not a parent of an <x> element; or, that has no attributes.

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

The result is a node set containing the following <x> elements, listed below with its children:

<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>

Community Additions

ADD
Show:
© 2015 Microsoft