Mark Wilson I am the creator of TopXML. I am available for international and local (Australia) contracts. I am a Solution Architect/Business Analyst. I have worked in IT in several countries (NZ, Australia, South Africa, UK) building and training teams for government and very large non-governmental organizations. I am ex-Microsoft Consulting Services. I wrote the first book on Microsoft XML published in 2000 called XML Programming with VB and ASP. Most recently I have been building tools for the SEO industry. Ask me for a 37 point SEO health-checkup for your website.
This is an excerpt from
Chapter 4 of the New Riders
book called
Inside XSLT written by Steven Holzner.
PLEASE NOTE: To work with the XSLT and XPath in this
document TopXML recommends you use the demo version of Xselerator
XSL Editor
Predicates are true XPath expressions, and XPath is much more of
a true language than patterns; for example, XPath expressions can
return not only lists of nodes, but also Boolean, string, and
numeric values. XPath expressions are not restricted to working
with the current node or child nodes, because you can work with
parent nodes, ancestor nodes, and more.
Chapter 7 gives its full attention to XPath, but it's worth
getting an introduction to the subject during this discussion about
patterns, because the predicate part of a pattern is its most
powerful part. There are all kinds of expressions that you can work
with in predicates; the following list includes some possible
types, which are explored in the next sections:
As its name implies, a node set is simply a set of nodes (and it
may contain only a single node). The expression child::PLANET
returns a node set of all <PLANET> elements. The expression
child::PLANET/child::NAME returns a node list of all <NAME>
elements that are children of <PLANET> elements. To select a
node or nodes from a node set, you can use the following functions
that work on node sets in predicates.
last(). Returns the
number of nodes in a node set.
position(). Returns
the position of the context node in the context node set (starting
with 1).
count(node-set). Returns the number of nodes in a node set.
Omitting node-set makes this function use the context
node.
id(string
ID). Returns a node set containing the element whose ID matches
the string passed to the function, or an empty node set if no
element has the specified ID. You can list multiple IDs separated
by white space, and this function returns a node set of the
elements with those IDs.
local-name(node-set). Returns the local name of the first
node in the node set. Omitting node-set makes this function
use the context node.
namespace-uri(node-set). Returns the URI of the namespace of
the first node in the node set. Omitting node-set makes this
function use the context node.
name(node-set). Returns the full, qualified name of the
first node in the node set. Omitting node-set makes this
function use the context node.
Here's an example; in this case, I number the elements in the
output document using the position() function:
Here's the result, where you can see that the planets are
numbered:
<HTML>
<HEAD>
<TITLE>
The Planets
</TITLE>
</HEAD>
<BODY>
<P>
1. Mercury
</P>
<P>
2. Venus
</P>
<P>
3. Earth
</P>
</BODY>
</HTML>
You can also use functions that operate on node sets in
predicates, as I do here: PLANET[position() = last()], which
selects the last <PLANET> child of the context node.
You can also use Boolean values in XPath expressions. Numbers
are considered false if they're zero, and true otherwise. An empty
string, "", is also considered false, and all other strings are
considered true.
You can use the following XPath logical operators to produce
Boolean true/false results:
!= means "is not
equal to"
< means "is less
than" (use < in XML or XSL documents)
<= means "is less
than or equal to" (use <= in XML or XSL documents)
= means "is equal
to" (C, C++, Java, JavaScript programmers take note: this operator
is one = sign, not two).
Note in particular that you shouldn't use < directly in XML
or XSL documents, so you should use the entity reference <
instead.
You can also use the keywords and and or to connect Boolean
clauses with a logical And or Or operation, and you can use not to
flip the logical sense of an expression, from true to false, or
false to true.
In the following example, I identify Earth's <PLANET>
element and place the strings "Earth", "needs", "no", and
"introduction." in the table rather than Earth's numeric data. I
identify which planet is Earth with the predicate "[NAME='Earth']",
which checks the value of the <NAME> element, which in turn
is its enclosed text. I also provide a template for the other
planets, matching the predicate "[NAME!='Earth']":