XPath

Page - 1 -|  2  |  3  

 
   
XPath Expressions

 

XPath (XML Path language) is typically the means for referring to and retrieving information from an XML document. It's probably the most involved of the XML technologies. It's sort of the 'heart' of XML, perhaps. On first inspection, it might look as complicated as regular expressions, or APL, or heiroglyphics, or the like. And some will make it out to be more complicated than need be. But there are subtleties and a lot of inconsistencies, in these early versions. So in a sense, it can get complicated. The XPath 'command' is called an - expression. It can be composed of different parts, or 'steps'. And it's a model or logic peculiar to a particular version. This, following, refers to the first officially recommended XPath standard, version 1.0. Much might change in version 2.0. Many people probably hope so.

XPath is typically used with XSLT. But XPath is used with the DOM, as well, and again is generally a means of reading information from an XML document. You'll sometimes see the word, pattern, used instead of, expression, when referring to something like the XSLT attribute, match, for example. All XSLT 'patterns' are XPath expressions. It's just that certain XPath expression can't be used with something like match, is all. And there is a difference between match patterns and selecting subsets using the same or similar XPath expressions.

 
Root Node

 

XML, the source document, is read by the 'parser', 'core', library routines, etc., such as Microsoft's msxml.dll, and transformed into an internal memory representation, a node-set, or tree, called an - infoset. Other nodes can be added to this infoset that weren't part of the XML, itself. These early efforts at XPath, and the rest, however, are a bit confused. And this shows up, particularly in XPath version 1.

DOM also requires its infoset - or internal tree structure of the source XML document. But it's slightly different than that used for XPath. And, even apart from that, an important confusion occurs in considering the idea of a root. The root element in XML is that topmost element which has no 'siblings' and no superior or 'parent' elements. But in creating this internal representation, another root is created above that XML root element. And that new root applies to the entire document, and can be called the - root node - or document element, and so on. Comments, and processing instructions (like the xsl 'boilerplate' at the top of an XSLT program/template) can be placed as 'siblings' of the XML root element, when transformed or "serialized" into this internal tree structure. The concepts and terminology are still all being worked out. And there are contradictions and inconsistencies. A lot of this wasn't addressed, apparently, in the earliest approved drafts for version 1, which don't even mention some of these terms.

 
Pattern Position

 

Given all that, and not to scare you much, XPath views the XML as an outline, as noted, and converts all parts of the XML into an outlined/hierarchical internal 'infoset' representation, consisting of various types of - nodes. The XML elements, comments, attributes, etc become - nodes - to XPath. They are nodes in a 'tree', or hierarchy, or whatever you call it.

A pattern can be used to match certain nodes. This is how templates are triggered. The pattern will give the position of that node in the overall document infoset, or tree. This is different than selecting sub-trees, sub-sets from the entire document.

 
Nodes

 

A subset of nodes can also be selected from the infoset for the entire document. XPath has seven different node types, mentioned on the next page. One of those is - element. So the element from from the HTML, say, is stored in the internal tree representation by the XML parser as a node, yes, but as a node of the "element" type. A little round-about.

 
Data Types

 

Any XPath expression can select/return a sub-branch, or subset of nodes, simply - a node-set. And it can also return data types - boolean (yes/no), string, and number, in addition to node-set. Even a single node would count as a node-set. And a node-set can also be referred to as a - node list.

 
Location Paths

 

Let's see a sample XML document, and call it, x.xml:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="trans.xsl"?>
 
<root>
   <file>
      <sourcepath>c:\xslt\trans.xsl</sourcepath>
      <targetpath>c:\windows\temp\tmp.htm</targetpath>
   </file>
 
   <image>
      <name>Mat9b</name>
      <height>150</height>
      <width>150</width>
      <filesize>27.95</filesize>
      <colors>1</colors>
      <designer>myself</designer>
      <path>./project/tiles/Metal/mat9b.png</path>
   </image>
 
   <body>
      <bgcolor>E1E1E1</bgcolor>
      <alink>5709DB</alink>
      <vlink>393F29</vlink>
      <link>1F3E00</link>
      <text>141414</text>
      <background>./project/tiles/misc/stucco2.jpg</background>
   </body>
 
   <externalLink>
      <elink>
         <URLloc>ftp://test 2</URLloc>
         <Descrip>Nothing much to say</Descrip>
         <NameLabel>test 2</NameLabel>
      </elink>
      <elink>
         <URLloc>http://test1</URLloc>
         <Descrip>no link here</Descrip>
         <NameLabel>test1</NameLabel>
      </elink>
   </externalLink>
 
</root>

 

Let's say you want to read the source and target file values, if any. XPath has a basic type of expression called a - location path. You run through the internal tree structure, the nodeset, built from the XML source, seemingly as if it were a directory listing. The forward slash is used, as with web addresses. So starting at - root - the next element down is - root/file. Under file you would have - root/file/targetpath. It's that simple. And that's if you're starting at root, every time, or rather root element node (not root node - or 'document element', 'document node', some terminology in need of clarification).

It gets a little confusing, yet again, because while this probably started out as a way to navigate the nodeset as if it were just directory listing, generalizing each 'directory', as it were, changes things quite a bit. The above is, in a way, just a special case of a location path. And the 'path' becomes not so much like a directory path, except in a special case, but more like a compound search - something like a SQL SELECT, or whatever example you might prefer.

 
Location Steps

 

So the real 'core' of XPath is what is termed the - location step. It can just be the name of a node. It can be a path. It's an - expression - in either case. And each 'directory' in the example becomes merely a special case, because these steps rather refer to a number of nodes, a node-set, according to the form:

AXIS::NODES[PREDICATE]

 

The predicate is sometimes called a - filter (like a SQL WHERE clause, or whatever other example you prefer). It 'filters' the node-set - AXIS::NODES - whatever the axis and whatever particular nodes. There are different axes, defined and described on the next page. And these have shorthand notations, or defaults that can be used if nothing is specified. But for defaults, and shorthands, and optional parts, each step along the path is not really a 'directory', but much more generally is really following the form, above. Each 'step' is a node-set. The final result can be a node-set, or one of the other three datatypes that can result from a location step - which again were, boolean (yes/no), string, and number. But each step to the right assumes a node-set created 'off to the left'.

In other words, taking the idea of a directory structure, previously, let's say you have root/dirTop/dirA. Even in just that structure, this path sort of winnows down, reduces, the number from a large set, or selection. So under dirTop you have all the subdirectories for that. But once you say, dirA, you are further narrowing down the selection. And that's how you look at a left-right selective reduction of an Xpath, with the slash or double slash serving as the separator - called the, location step operators. The single slash just indicates the refinement of the set, to the right. It separates the location steps. But the double slash indicates that and also that any number of sub-categories, and categories below that, can be examined by the expressions to the right; recursive descent, explained below.

So each step along the way produces a node-set. If there's another step to the right, the resulting node-set from that will likely be different. It's node-sets, narrowed down more and more. The axis, node, and predicate can be included in any step along the way. Just as example from an XSLT template used to generate these sites:

//link[@Style='AltTitle']//anchor[1]

Which gathers all the elements named, link, but only if they have an attribute named, style, which has a value of, AltTitle, and then further reduces that to all the first occurrences of elements named, anchor, however further down in the tree, from each such link element. It's explained, as you read on. (In the specific instance from which this was taken, the XML has only one link element with a "style='AltTitle'".)

 
XSLT Example

 

Okay. XSLT needs XPath to read information out of the XML document, above, and as mentioned. So, some sort of XSLT transform/program, that we're calling, trans.xsl, for the XML document, above, might look like:

 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 
<xsl:output omit-xml-declaration="yes" indent="yes"/>
 
<xsl:template match="/">
 
   <xsl:for-each select="//*">
      <xsl:value-of select="position()"/>)
      <xsl:value-of select="name()"/> --
      (<xsl:value-of select="parent::*[name()='image']"/>) --
      (<xsl:value-of select="."/>) --
      (<xsl:value-of select="text()"/>)<br/>
   </xsl:for-each>
 
</xsl:template>
 
</xsl:stylesheet>

 

And just taking the last few lines generated from this program:

 
17) link -- () -- (1F3E00) -- (1F3E00)
18) text -- () -- (141414) -- (141414)
19) background -- () -- (./project/tiles/misc/stucco2.jpg) -- (./project/tiles/misc/stucco2.jpg)
20) externalLink -- () -- ( ftp://test 2 Nothing much to say test 2 http://test1 no link here test1 ) -- ()
21) elink -- () -- ( ftp://test 2 Nothing much to say test 2 ) -- ()
22) URLloc -- () -- (ftp://test 2) -- (ftp://test 2)
23) Descrip -- () -- (Nothing much to say) -- (Nothing much to say)
24) NameLabel -- () -- (test 2) -- (test 2)
25) elink -- () -- ( http://test1 no link here test1 ) -- ()
26) URLloc -- () -- (http://test1) -- (http://test1)
27) Descrip -- () -- (no link here) -- (no link here)
28) NameLabel -- () -- (test1) -- (test1)

 

So, line by line, to begin with:

 
<xsl:template match="/">

 
 
Xpath Used in Attributes

 

The XSLT stylesheet element will contain one or more elements called, xsl:template. These are the declarative 'procedures' in the program, basically. Now the match attribute uses an - expression. The expression is written in XPath, and this is the way XPath is used. XPath, in other words, is used in attribute values, double-quoted. If you need to quote in an XPath expression, itself, you can use single-quotes (as you see with name = 'image'). What this single slash, in particular, says is start at the very first node in the XPath infoset - at the root node. Because of implied/default axes, it also suggests something else. But that's mentioned, later.

 
Xpath in XSLT 'loops'

 

But then the for-each loop construct uses a double slash with an asterick. The double slash is an XPath shorthand:

 
<xsl:for-each select="//*">

 

The for-each is using an XPath expression that goes through every node. The double slash indicates 'recursive' searching or descent. It's a shorthand notation. And it goes down level, by level, automatically. The asterick indicates - match every element (not necessarily every type of node). It's basically looking at everything in this example. But it's also selecting everything. If it wasn't this double-slash asterick, but something else, then you could select a subset from the overall infoset, using this select.

 
<xsl:value-of select="position()"/>)
<xsl:value-of select="name()"/> --

 
 
Functions

 

The position() and name() are both XPath - functions - in this case, node-set functions. These functions are grouped according to data type. So you have four data types. Therefore, XPath uses four different types of functions. You can see from the partial output, above, that name() reports the name of the element, here. The position() returns a scalar, starting at 1. Different nodes, in turn, are examined, analyzed - evaluated. Name() and position() are evaluating each node, in turn. In fact, an XPath expression can be placed in the parentheses of a function, so that name(), in this case, will give the name of the node (or first node, in a node-set) of that expression. Otherwise, if just parentheses, it gives whatever may be the - current node. In this case, the 'loop' goes down the node-set, and the current node changes each time to the next in the list. There's a slight twist on that, as seen in the value for position(), and keeping in mind the idea of the XML document as a 'table of contents', one can go down that list, regardless of nesting/indenting, numbering every line, in order. That's position(). It's the ordinal position in a node-set (from an XPath expression), ignoring 'level', but in the order found in the XML source - the document order.

 
(<xsl:value-of select="parent::*[name()='image']"/>) --

 

This actually returns a value for the seven nodes at positions 6-12 - all those elements under the image element - when the for-each loop makes each of those nodes, in turn, the - current node. Again, the name() function is used to check a particular node name. And something called the parent axis, indicated by the particular reserved word, parent (and also, as seen above, that double colon notation), is used to specify that the name() being checked is that of the superior/parent element of the current node. So the parent - the asterick is finding all the elements one level up, but any node only has one parent - has to be named, image, in this example. And there are seven elements that are under image. As for what it returns, this returns the same string for all seven elements under image. And that string is just all the values for those elements, run together side by side. Here:

 
6) name -- ( Mat9b 150 150 27.95 1 myself ./project/tiles/Metal/mat9b.png ) -- (Mat9b) -- (Mat9b)
7) height -- ( Mat9b 150 150 27.95 1 myself ./project/tiles/Metal/mat9b.png ) -- (150) -- (150)

 

The reason is that because nothing was specified, the default is just all the text in that image node. If you strip away the stuff in the angle brackets, what you have left, under image, is that string, all run together; the actual text inside <image> </image> . Nodes have various data associated with them, as nodes. The node name, for example, is part of that node. And this, too, is a string data-type associated with, part of the structure of, any node. And in the case of nodes based on XML elements, it's all the raw text in that element.

Read on.