9.5 Unabbreviated Location Paths


9.5 Unabbreviated Location Paths

Up until this point, we've been using what are called abbreviated location paths . These are easy to type, not usually verbose, and very familiar to most people. They're also the kind of XPath expression that works best for XSLT match patterns. However, XPath also offers an unabbreviated syntax for location paths, which is more verbose but perhaps less cryptic and definitely more flexible than abbreviated location paths.

Every location step in a location path has two required parts , an axis and a node test, and one optional part, the predicates. The axis tells you which direction to travel from the context node to look for the next nodes. The node test tells you which nodes to include along that axis, and the predicates further reduce the nodes according to some expression.

In an abbreviated location path, the axis and the node test are combined, while in an unabbreviated location path, they're separated by a double colon ( ::) . For example, the abbreviated location path people/person/@id is composed of three location steps. The first step selects people element nodes along the child axis. The second step selects person element nodes along the child axis. The third step selects id attribute nodes along the attribute axis. When rewritten using the unabbreviated syntax, the same location path is child::people/child::person/attribute::id .

These full, unabbreviated location paths may be absolute if they start from the root node, just as abbreviated paths can be. The full form /child::people/child::person , for example, is equivalent to the abbreviated form /people/person .

Unabbreviated location paths may be used in predicates as well. For example, the abbreviated path /people/person[@born<1950]/ name [first_name="Alan"] becomes /child::people/child::person[ attribute::born < 1950 ] /child::name[ child::first_name = "Alan" ] in the full form.

Overall, the unabbreviated form is quite verbose and not used much in practice. However, it does offer one crucial ability that makes it essential to know: it is the only way to access most of the axes from which XPath expressions can choose nodes. The abbreviated syntax lets you walk along the child, parent, self, attribute, and descendant-or-self axes. The unabbreviated syntax adds eight more axes:


All element nodes that contain the context node, that is, the parent node, the parent's parent, the parent's parent's parent, and so on up through the root node in reverse document order.


All nodes that follow the context node and are children of the same parent node in document order. Attribute and namespace nodes do not have any siblings.

preceding -sibling

All nodes that precede the context node and are children of the same parent node in reverse document order.


All nodes that follow the end of the context node in document order except for descendant, attribute, and namespace nodes.


All nodes that precede the start of the context node in reverse document order except for ancestor, attribute, and namespace nodes.


If the context node is an element, all namespaces in scope on the context node, whether declared on the context node or one of its ancestors . If the context node is not an element, then the empty set.


All descendants of the context node but not the context node itself.


All ancestors of the context node and the context node itself.

Example 9-4 demonstrates several of these axes using the full unabbreviated syntax. The goal is to produce a list of person elements that look more or less like this (after accounting for whitespace):

 <dt>Richard P Feynman</dt> <dd>   <ul>     <li>physicist</li>     <li>Playing the bongoes</li>   </ul> </dd> 

Example 9-4. An XSLT stylesheet that uses unabbreviated XPath syntax
 <?xml version="1.0"?> <xsl:stylesheet version="1.0"                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">         <xsl:template match="/">     <dl>       <xsl:apply-templates select="descendant::person"/>     </dl>   </xsl:template>         <xsl:template match="person">     <dt><xsl:value-of select="child::name"/></dt>     <dd>       <ul>         <xsl:apply-templates select="child::name/following-sibling::*"/>       </ul>     </dd>   </xsl:template>         <xsl:template match="*">     <li><xsl:value-of select="self::*"/></li>   </xsl:template>         <xsl:template match="homepage"                xmlns:xlink="http://www.w3.org/1999/xlink">     <li><xsl:value-of select="attribute::xlink:href"/></li>   </xsl:template>       </xsl:stylesheet> 

The first template rule matches the root node. It applies templates to all descendants of the root node that happen to be person elements. That is, it moves from the root node along the descendant axis with a node test of person . This XPath expression could have been rewritten in the abbreviated syntax as //person .

The second template rule matches person elements. It places the value of the name child of each person element in a dt element. The location path used here, child::name , could have been rewritten in the abbreviated syntax as the single word name . Then it applies templates to all elements that follow the name element at the same level of the hierarchy. It begins at the context node person element, then moves along the child axis to find the name element. From there it moves along the following-sibling axis looking for elements with any name ( * ) after the name element that are also children of the same person element. There is no abbreviated equivalent for the following-sibling axis, so this really is the simplest way to make this statement.

The third template rule matches any element not matched by another template rule. It simply wraps that element in an li element. The XPath expression self::* selects the value of the currently matched element, that is, the context node. This expression could have been abbreviated as a single period.

The fourth and final template rule matches homepage elements. In this case we need to select the value of xlink:href attributes, so we move from the context homepage node along the attribute axis. The node test is looking for the xlink:href attributes. (More properly, it's looking for an attribute with the local name href whose prefix is mapped to the http://www.w3.org/1999/xlink namespace URI.)

XML in a Nutshell
XML in a Nutshell, Third Edition
ISBN: 0596007647
EAN: 2147483647
Year: 2003
Pages: 232

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net