Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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 |
---|---|
|
A node set containing |
|
A node set containing |
|
A node set containing all |
|
The node set containing all |
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 |
|
Comparisons |
5 |
|
Comparisons |
6 |
|
Union |
7 |
|
Boolean not |
8 |
|
Boolean and |
9 |
|
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>