Creating Compound Location Paths
In XPath, you can combine location paths with the |, or "pipe" character. We've already seen that at work like this:
<xsl:template match="name | day">
. . . </xsl:template>
You can use any kind of location paths with the pipe character, like this:
<xsl:template match="name/firstName | day/author/lastName">
. . . </xsl:template>
When you use a compound location path, each path is evaluated separatelythat is, the context node for the first path doesn't affect the context node for the other path. And you're not restricted to two paths; you can connect as many as you like with pipes:
<xsl:template match="name/firstName | day/author/lastName | distance | mass/kilograms"> . . . </xsl:template>
When it comes to predicates, however, the situation is different. In XPath, you combine conditions in a predicate with the and and or operators. For example, if you wanted to match all <distance> elements that have units attributes set to "million miles" and language attributes set to "English", you could use the and operator like this:
<xsl:template match="distance[@units='million miles' and @language='English']"> <distance>This is the planet Mercury, closest to the Sun.</distance> </xsl:template>
Here's another example: child::*[self::name or self::mass], which returns both the <name> and <mass> children of the context node.
You can connect as many conditions in a predicate as you want using and and or. And if it gets confusing, you can use parentheses like this:
<xsl:template match="author[(@firstName='Cary') and (@lastName='Grant)]"> <distance>This is the planet Mercury, closest to the Sun.</distance> </xsl:template>
Note also that compound location paths can also have predicates, of course, including compound predicates.
Using Quotation Marks
Notice the quotation marks hereto avoid confusing the XSLT processor, we're using single quotes to surround the attribute values here, because the whole XPath expression is surrounded in double quotes. You could also use the or operator if you wanted to match <distance> elements that have units attributes set to "million miles" or language attributes set to "English", like this:
<xsl:template match="distance[@units='mil lion miles' and @language='English']"> <distance>This is the planet Mercury, closest to the Sun.</distance> </xsl:template>
It's also legal to nest predicates. Here's how you might select all <project> elements that have <name> descendants that in turn have a preceding sibling <active> element:
You can also nest predicates when using compound location paths and even compound predicates.
Using Predicates Without Operators
The predicates we've used so far usually use operators, as in the location step author[position()=4], where we're using the = operator (we'll see all the available operators in the next chapter). However, you don't need to use operators at all in predicates if you just want to test for the existence of a node.
For example, if you want to find all <notation> elements that contain at least one <author> element, you can use this location path: //notation[descendant::author].
That's it for this chapter on location steps and location paths. We saw how XPath works with the data model introduced in Chapter 2 by using location paths, which are made up of location steps. Each location step, in turn, is made up of an axis, a node test, and a predicate. In Chapter 4, we're going to get more details on creating location paths as we see the operators and functions you can use in XPath predicates.