The XPath pattern syntax is described formally in the XPath specification.
Here we're going to look at the syntax in abstract, but less formal terms:
An XPath pattern is a 'location path', a location path is
absolute if it begins with a slash ("/") and relative otherwise
A relative location path consists of a series of steps, separated
by slashes
A step is an axis specifier, a node test, and a predicate
The formal syntax is made more complicated by the fact that it must
describe both the abbreviated and unabbreviated syntaxes
Node Tests
Node tests are most frequently element names, but other node tests are
possible:
name
Matches <name> element nodes
*
Matches any element node
namespace:name
Matches <name> element nodes in the specified namespace
namespace:*
Matches any element node in the specified namespace
comment()
Matches comment nodes
text()
Matches text nodes
processing-instruction()
Matches processing instructions
processing-instruction('target')
Matches processing instructions with the specified target (<?target
...?>
node()
Matches any node
Predicates
Predicates occur after the node test in square brackets. A wide range
of expressions are possible.
nodetest[1]
Matches the first node
Most node tests return nodes in document order, only the tests which
select ancestor or preceding elements return nodes in reverse document order.
The practical result of this is that the "first" node is almost
always the one closest to the context node, although parenthesis can change
the effective order.
nodetest[position()=last()]
Matches the last node
nodetest[position() mod 2 = 0]
Matches even nodes
element[@id='foo']
Matches the element(s) with id attributes whos value is "foo"
element[not(@id)]
Matches elements that don't have an id attribute
author[firstname="Norman"]
Match <author> elements that have <firstname> children with the
content "Norman".
author[normalize-space(firstname)="Norman"]
Match "Norman" without regard to leading and trailing space.
Predicate expressions can be more-or-less arbitrarily complex.
Axis Specifiers
The axis of a node test determines what general category of nodes may
be considered for the following node test. There are thirteen axes:
ancestor
Ancestors of the current node
ancestor-or-self
Ancestors, including the current node
attribute
Attributes of the current node (abbreviated "@")
child
Children of the current node (the default axis)
descendant
Descendants of the current node
descendant-or-self
Descendants, including the current node (abbreviated "//")
following / following-sibling
Elements which occur after the current node, in document order
preceding / preceding-sibling
Elements which occur before the current node, in document order (returned
in reverse-document order)
namespace
The namespace nodes of the current node
parent
The parent of the current node (abbreviated "..")
self
The current node (abbreviated ".")
A Few More Patterns
Now that we've seen the unabbreviated syntax, let's look at a few more
patterns
ancestor::table
Matches ancestor <table> elements
following-sibling::paramdef
Matches the following <paramdef> siblings
ancestor-or-self::*/@sepchar
Matches the sepchar attribute on the current element or any ancestor
of the current element
Applying Style Recursively
One model for applying style is to allow the process to run recursively,
driven primarily by the document. A series of templates is created, such that
there is a template to match each context, then these templates are recursively
applied starting at the root of the document.
There are two obstacles to overcome when using the recursive model,
how to arbitrate between multiple patterns that match and how to process the
same nodes in different contexts.