XPath views nodes along axes. An axis refers to various ways that you can locate nodes along the edges (branches) of a tree structure, either forward or backward. For example, the parent axis refers to the parent of a node, and the self axis refers only to a node itself. You can specify a few of the axes by using the abbreviated syntax, such as the parent (../given), child (given), and self (.) axes, but you can also specify them using the unabbreviated syntax, as in parent::given, child::given, and self::node( ). One of the reasons you would want to use unabbreviated axes specifiers is because they allow you to find and access nodes that are not in the current node list. Axes are oriented along a forward or reverse direction. Only 4 of the 13 axes have a reverse orientation. For example, the ancestor axis refers to nodes that come before the context node in the reverse direction, up to and including the root node. The descendant axis, on the other hand, includes nodes that come after the context node in the forward direction. XPath defines 13 different axes, which are all listed and described in Table 4-2.
4.6.1 Unabbreviated SyntaxThe axes can be explicitly expressed using XPath's unabbreviated syntax, by connecting an axis name with a node name or a node test (see Section 4.7, later in this chapter). Table 4-3 compares a few abbreviated and unabbreviated syntax examples to help you understand the relationship between the two.
The following stylesheet shows you how axes and the unabbreviated syntax work together. The stylesheet, shown in Example 4-6, is called unabbreviated.xsl and is similar to pattern.xsl, which you saw earlier in this chapter. Example 4-6. A stylesheet using the full axis syntax<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:apply-templates select="child::names"/> </xsl:template> <xsl:template match="child::names"> <xsl:apply-templates select="child::name[4]/attribute::title"/> </xsl:template> <xsl:template match="child::name[4]/attribute::title"> <xsl:text>The XML 1.0 WG's </xsl:text> <xsl:value-of select="self::node( )"/> <xsl:text> was </xsl:text> <xsl:value-of select="parent::name/child::given"/> <xsl:text> </xsl:text> <xsl:value-of select="parent::name/child::family"/> <xsl:text>.</xsl:text> </xsl:template> </xsl:stylesheet> Lines in the stylesheet that use unabbreviated syntax are highlighted in bold. The parent, child, self, and attribute axes are connected to node names using a connector (::). The parent axis may be abbreviated as .., so that parent::name/child::given could be ../given. The self axis is connected to node( ). This syntax looks like a function call, but it's really not. It's a node test that tests to see whether a node matches a particular criterion. The node( ) test matches any node and is sometimes called a wildcard (though the word wildcard doesn't appear in the XPath 1.0 spec). If you apply unabbreviated.xsl to names.xml, using: xalan names.xml unabbreviated.xsl you get the following line as a result: The XML 1.0 WG's technical lead was James Clark. 4.6.2 Reaching Out of Context with Unabbreviated SyntaxAs I mentioned earlier, you can use axes to reach for nodes that are not in context. As usual, I'll illustrate how to do this with an example. When the stylesheet shown in Example 4-7, ancestor.xsl, processes the last name node in names.xml, it also processes the first name node in the document by using the ancestor axis. Example 4-7. A stylesheet using the ancestor axis<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:apply-templates select="child::names"/> </xsl:template> <xsl:template match="child::names"> <xsl:apply-templates select="child::name[18]"/> </xsl:template> <xsl:template match="child::name[18]"> <xsl:value-of select="ancestor::names/child::name[1]/child::given"/> <xsl:text> </xsl:text> <xsl:value-of select="ancestor::names/child::name[1]/child::family"/> <xsl:text> is first on the list, and </xsl:text> <xsl:value-of select="child::given"/> <xsl:text> </xsl:text> <xsl:value-of select="child::family"/> <xsl:text> is last.</xsl:text> </xsl:template> </xsl:stylesheet> The node processed by the last template in the stylesheet is the last (child::name[18]) name node in names.xml. While this template processes the last name node, it also finds an ancestor, the names node, and then processes the first name child of names called given (ancestor::names/child::name[1]/child::given) and the first name child of names called family (ancestor::names/child::name[1]/child::family). Apply it with: xalan names.xml ancestor.xsl The result of processing names.xml with this stylesheet is as follows: Paula Angerstein is first on the list, and John Tigue is last. |