XPath 2.0 also has a number of numeric functions, designed to work with these numeric types: -
` xs:decimal ` -
` xs:integer ` -
` xs:float ` -
` xs:double ` These functions also apply to types derived by restriction from these types. The XQuery 1.0 and XPath 2.0 Functions and Operators document lists a large number of ` op ` functions that specify how various numeric operators work on different data types. Here are some of the ` op ` functions describedyou can tell what operator each function is describing by its name : -
` op:numeric-add ` Addition (+) -
` op:numeric-subtract ` Subtraction () -
` op:numeric-multiply ` Multiplication (*) -
` op:numeric-divide ` Division ( ` div ` ) -
` op:numeric-integer-divide ` Integer division ( ` idiv ` ) -
` op:numeric-mod ` Modulus ( ` mod ` ) -
` op:numeric-unary-plus ` Unary plus (+) -
` op:numeric-unary-minus ` Unary minus (negation) () These functions are not callable from XPath 2.0 expressions; they underpin the operators in the language. However, you can work with a set of numeric functions in the ` fn ` namespace. Each of the ` fn ` functions returns a value of the same type as the type of its argument. If the argument is the empty sequence, the empty sequence is returned, and if the argument is ` xdt:untypedAtomic ` , it is converted to ` xs:double ` . Here's an overview of the callable numeric functions: -
` fn:floor ` returns the largest number with no fractional part that is less than or equal to the value you pass. -
` fn:ceiling ` returns the smallest number with no fractional part that is greater than or equal to the value you pass. -
` fn:round ` rounds to the nearest number with no fractional part. -
` fn: round-half-to-even ` accepts a number and a rounding precision value and returns a number rounded to the precision you've requested . Note that if the fractional part of the value you pass is .5, the result is the number whose least significant digit is even. We'll take a look at them here. #### The ` fn:floor ` Function The ` fn:floor ` function returns the largest numberthat is, the closest to positive infinitythat has no fractional part, such that the returned number is not greater than the value you pass to this function. Here's the signature of this function: fn:floor( $srcval as numeric?) as numeric? Here are some examples: fn:floor(2.3) returns 2 fn:floor(1.5) returns 1 fn:floor(-9.5) returns -10 And here's an example putting this function to work in an XSLT 2.0 stylesheet. In this example, we'll determine whether a number is an integer, and we start by assigning that number to a variable named ` $number ` : <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="number" select="1.5" /> . . . If ` floor($number) = $number ` , the number is indeed an integer, and we can insert the message ` "That number is an integer." ` in the result document like this: <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="number" select="1.5" /> . . . <xsl:template match="/"> <xsl:value-of select="if (floor($number) = $number) then 'That number is an integer.' . . . </xsl:template> On the other hand, if ` floor($number) != $number ` , we can insert the message ` "That number is not an integer." ` in the result document, as you see in ` ch09_11.xsl ` (Listing 9.11). ##### Listing 9.11 Using the ` fn:floor ` Function ( ` ch09_11.xsl ` ) <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="number" select="1.5" /> <xsl:template match="/"> <xsl:value-of select="if (floor($number) = $number) then 'That number is an integer.' else 'That number is not an integer.'"/> </xsl:template> </xsl:stylesheet> And here's the result when you use Saxon on this stylesheetas you can see, this code knows that 1.5 is not an integer: <?xml version="1.0" encoding="UTF-8"?> That number is not an integer. #### The ` fn:ceiling ` Function The ` fn:ceiling ` function returns the smallestthat is, closest to negative infinitynumber with no fractional part, such that the returned number is not less than the value you pass this function. Here's what this function's signature looks like: fn:ceiling( $srcval as numeric?) as numeric? Here are some examples: fn:ceiling(9.3) returns 10. fn:ceiling(1.5) returns 2. fn:ceiling(-4.5) returns -4. Here's an example using ` fn:ceiling ` . In this case, say you have one and a half truckloads of iron ore to move and want to know how many trucks you'll need. We start by setting up a variable, ` $numberofTruckLoads ` : <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="numberofTruckLoads" select="1.5" /> . . . And passing this variable to the ` fn:ceiling ` function tells us how many trucks we'll need to transport the load; you can see the XPath code in ` ch09_12.xsl ` (Listing 9.12). ##### Listing 9.12 Using the ` fn:ceiling ` Function ( ` ch09_12.xsl ` ) <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="numberofTruckLoads" select="1.5" /> <xsl:template match="/"> <xsl:value-of select="concat('You will need ', string(ceiling($numberofTruckLoads)), ' trucks.')"/> </xsl:template> </xsl:stylesheet> Here's the result: <?xml version="1.0" encoding="UTF-8"?> You will need 2 trucks. #### The ` fn:round ` Function The ` fn:round ` function is XPath 2.0's main rounding function. The ` fn:round ` function returns the number with no fractional part that is closest to the value you pass. If there are two such numbers , this function returns the one closest to positive infinity. Here's what the signature of this function looks like: fn:round( $srcval as numeric?) as numeric? Here are some examplesnote in particular that ` fn:round(-9.5) ` returns 9, not 10: fn:round(1.2) returns 1. fn:round(6.5) returns 7. fn:round(6.4999999) returns 6. fn:round(-9.5) returns -9. USING ` fn:round ` AND ` fn:floor ` ` fn:round( ` ` $srcval ` ` ) ` returns the same value as ` fn:floor( ` ` $srcval ` ` + 0.5) ` . Here's an example using this function in XSLT 2.0; say you're in charge of the movie reviews of a newspaper and have to multiply the average number of stars awarded to a movie, like 3.73, by your reviewers and come up with a whole number. You can use the ` fn:round ` function to do that, as you see in ` ch09_13.xsl ` (Listing 9.13). ##### Listing 9.13 Using the ` fn:round ` Function ( ` ch09_13.xsl ` ) <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="movieName" select="Casablanca" /> <xsl:variable name="numberOfStars" select="3.73" /> <xsl:template match="/"> <xsl:value-of select="concat('Casablanca got ', string(round($numberOfStars)), ' stars.')"/> </xsl:template> </xsl:stylesheet> And here's the result: <?xml version="1.0" encoding="UTF-8"?> Casablanca got 4 stars. #### The ` fn:round-half-to-even ` Function The ` fn:round-half-to-even ` function gives you a chance to specify the rounding precision yourself. There are two ways to use itpassing it a value, and passing a value and precision: fn:round-half-to-even( $srcval as numeric?) as numeric? fn:round-half-to-even( $srcval as numeric?, $precision as integer) as numeric? The first version of this function returns the nearest value to the value you pass that has no fractional part. If two values are equally closethat is, the fractional part of the value you pass is exactly .5the value returned is the one whose least significant digit is even. If you pass a ` $precision ` value to this function, you can set the precision yourself. In this case, the value returned is the nearest value to ` $srcval ` that is a multiple of 1/10 to the power of ` $pr ` ` e ` ` cision ` . As with the other form of this function, if two values are equally closethat is, the fractional part of the value you pass is exactly .5the value returned is the one whose least significant digit is even. Here is an example: fn:round-half-to-even(3.5) returns 4. On the other hand, the next example also returns 4: fn:round-half-to-even(4.5) returns 4. Here's an example that uses a precision of 2 (here we're using the standard exponentiation syntax you use in XPath 2.0; note that 1E+3 = 1000, 1E-1 = 1/10, and so on): fn:round-half-to-even(9.477512E+3, 2) returns 9477.51E0. You can also round to positive powers of 10 if you pass a negative value as the precision you want. For example, here's how you can round to the nearest 100: fn:round-half-to-even(12312.63, -2) returns 12300. AGGREGATE FUNCTIONS There are also some numeric functions that are specifically designed to work on sequences, called aggregate functions, such as ` max ` , ` min ` , ` count ` , ` avg ` , and ` sum ` , that are coming up in Chapter 12, "XPath 2.0 Node and Sequence Functions." |