XPath provides numerous functions for working with numbers and strings, and allows you to complete transformations and mine XML data without having to constantly bridge other APIs or technologies to do simple string and arithmetic operations. Adding, simple division, multiplication, and string searching are available as built-in functions of XPath.
Several XPath functions are available to you. In Example 5-4, multiplication is
used to apply a 20% discount to products. If you need to total a list
of products, you can use the sum
function, working with the same products data again:
<?xml version="1.0" encoding="UTF-8"?> <products> <item name="bowl" price="19.95"/> <item name="spatula" price="4.95"/> <item name="power mixer" price="149.95"/> <item name="chef hat" price="39.95"/> </products>
This time, in Example 5-5, you can use a
single XPath expression to generate a total. The expression sum(//@price)
returns the sum of the values
of all price elements in the products document. Now go back and modify
the stylesheet you created to discount the products, but this time add
in an xsl:value-of
element to
generate a total.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table>
<xsl:apply-templates/>
</table>
<p>Your Total:
<xsl:value-of select="sum(//@price)"/>
</p>
</body>
</html>
</xsl:template>
<xsl:template match="item">
<tr><td><b>Item: </b><xsl:value-of select="@name"/></td>
<td><b>Price: </b><xsl:value-of select="@price"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>
Figure 5-1 shows the result of the transformation (the HTML) in a browser.
In addition to sum
,
several other functions exist for working with numbers. The floor
function returns the largest integer
that is not greater than the argument. In other words, floor(3.4)
returns 3. The ceiling
function, floor
’s counterpart, returns the smallest
integer that is greater than the argument, e.g., ceiling(3.4)
returns 4. The round
function does exactly what you think
it should: round your decimal-ridden number to its closest integer.
For example, round(3.4)
returns 3,
while round(3.8)
returns 4.
In addition to functions for numbers, XPath supports functions for manipulating text. Most of these are valuable when doing conditional testing. Earlier you checked character data of child attributes with syntax such as:
ship[class="Intrepid"]
This expression returns any ship
element with a class
element beneath it containing the
character data Intrepid. This is a fine approach
for exact comparisons, but sometimes you’ll want finer control.
For example, the starts-with
function takes two arguments.
The first argument is what you’re looking for: the letters the string
may start with. The second argument is the node to evaluate. The
function returns true
or false
. For example, to get a true
or false return (in XSL) on whether a
ship element has a registry code that starts with NCC
, you can try the following
expression:
<xsl:value-of select="starts-with('NCC', ./registry-code/text( ))"/>
This expression returns true for every ship
in the ships.xml file. This type of Boolean return
may be of most benefit in XSLT, where you can use its if
-then
-else
language features for conditional processing. A variation on this
theme is the contains
function,
which returns true
if the second
argument contains the first argument.
If you know you have the string you want and are looking
to slice and dice it, the substring
and string-length
functions can
help you out. The substring
function takes up to three arguments. The first argument is the string
to manipulate; the second argument is the starting index within the
string; the third argument is the ending index. If the third argument
is omitted, it’s assumed to be the end of the string. The string-length
function is straightforward,
and returns the total length of the string as a number.
The translate
function takes a string parameter, as well as a list of characters to
replace and a list of corresponding replacement characters. Each
character in the second argument is replaced by the corresponding
character in the same position in the third argument. For example, the
expression translate("Wee Willy
Winky"
, "eily"
, "oaps")
returns the string Woo Wapps Wanks
. The concat
function returns the concatenation of
its two arguments.
Some functions in XPath are designed to work with elements and element traversal itself. These functions supply information related to XPath’s current position, and other positional type of information such as first matching element and last matching element. Node functions are fairly straightforward.
The position
function
returns a number equal to the context position from the expression
evaluation context. For example, to create a numbered list for the
ships of ships.xml, you could use
the position
function as shown in
the following stylesheet:
<?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="shiptypes"> <html> <body> <xsl:apply-templates select="ship"/> </body> </html> </xsl:template> <xsl:template match="ship"> <p> <xsl:value-of select="position( )"/>. <xsl:value-of select="@name"/> </p> </xsl:template> </xsl:stylesheet>
This code generates the following HTML output:
<html> <body> <p>1. USS Enterprise</p> <p>2. USS Voyager</p> <p>3. USS Enterprise</p> <p>4. USS Enterprise</p> <p>5. USS Sao Paulo</p> </body> </html>
The count
function
returns the number of nodes in the node set matching the argument. In
other words, count(//@name)
returns
the total number of name attributes within a document. The last
function returns a number equal to the
context size (the number of nodes) in the current expression.
The id
function
returns a node by specific id
. If
you create an element <name
id="a345">Chris
Jones</name>
and then use id('a345')
in your expression, this node is
returned. The localname
and
name
functions return both the
local name and the qualified name of the node in the current node set
that appears first in document order.
3.142.166.31