WEEK 1 DAY 10
Understanding Data Types

In the preceding lessons, you learned a great deal about selecting and manipulating elements and attributes of data. You learned how to select, display, and add data and also how to get certain information regarding the document as a whole or part thereof. The data values of elements and attributes themselves were ignored in the sense that what was in them was of no consequence. The values were just sent to the output. Whether the data represented text, dates, prices, or some other type of value wasn’t important. What a value represents might be very important, however. A date, for instance, may need to be displayed differently for different countries.

Today’s lesson covers the data in elements and attributes and the type of data they represent. What type of data a value represents is important if you want to manipulate the value—for instance, for calculations or for a more fine-grained control over what is done with certain data. Unfortunately, discussing data types is not possible without going into technical and theoretical details, so be prepared for some tough reading.

Today you will learn the following:

• What a data type is

• Which data types are available in XSLT

• How to compare different data with different data types

• How to convert data from one data type to another

Data Type Basics

The wonderful thing about XML is that it is all text. That’s what makes it easy to process for any computer system—Windows, Unix, Linux, or otherwise. Another great thing is that you can name elements and attributes in such a way that the name tells you something about the data in the element or attribute. However, the fact that an XML document is all text also means that all values are text. Now suppose that the value of one element is 2 and the value of another element is 5. Because these values are both text, adding them together will likely yield 25 instead of 7. Text has entirely different characteristics as opposed to numbers, and therefore reacts differently when you manipulate it.

What Is a Data Type?

NEW TERM

To help you get around the problem of all-text data, XSLT defines several data types. A data type defines how a data value is interpreted by the processor.

In essence, a data type tells the processor what to do with a value when a certain operation is requested on it. Type information also may be used to create an internal representation of an XML document, depending on how the data type is defined. This process is very much related to character encoding and output escaping. Whether characters are encoded in UTF-8, UTF-16, or some other encoding method can have a profound impact on what the data looks like when it is sent to the output. Unlike data types, however, character encoding doesn’t have an impact on how you work with the values. In fact, the processor can’t even tell you which encoding method was used when a character was stored or if it was output escaped.

Which representation is used to store data becomes significant when this information has an impact on how operations will behave when you apply them to the data. This is true for the conceptual level, where you need to think of numbers and other data types, but also on the storage level. You can store numbers in many different ways, for instance, each having different memory requirements. Most languages offer a variety of data types such as 8-bit integers, 16-bit integers, 32-bit integers, single-precision floating-point numbers and double-precision floating-point numbers.

NEW TERM

An integer is a whole number, without fractions; you know—the ones you count with. The terms 8-bit, 16-bit, and 32-bit represent the number of bits used to store the integer. A floating-point number is a number with fractions, such as 1.23 or 3.14159. The terms single precision and double precision do not refer to one or two decimals, rather to the amount of memory used and thus the range of numbers that it can hold.

As you can imagine, whether you’re using 8-bit or 32-bit integers makes quite a bit of difference on the amount of memory used. The latter takes up four times the amount of memory of the former. However, 8-bit integers usually can handle only numbers between–127 and 128 or 0 and 255, whereas 32-bit integers can deal with numbers in the billions. You might wonder what happens when you add two 8-bit integers with the value 255. Obviously, the result will no longer fit in an 8-bit integer.

As you can see, data types are important to processing your data correctly, so it is important for you to know which data types XSLT has, how XSLT determines the data type, and how you can work with different data types.

Data Types in XSLT

XSLT supports only a handful of data types:

• Boolean

• String

• Number

• Node-set

• Tree fragment

You have already worked with all of them, but not explicitly, because you weren’t yet aware of the existence of data types. Now that you know about the data types in XSLT, you are ready to learn how XSLT actually deals with them.

A data type is always relevant to a piece of data. This data either comes from a source document or from a parameter passed by the processor. All the data values in an XML document therefore are of some data type. As far as XML is concerned, all values are strings. XSLT sees these strings either as a string or a number. In an XML document, a value can’t have the Boolean data type. Booleans are of use only in expressions. Technically, node-sets and tree fragments also don’t exist within an XML source, but when you operate on nodes in XSLT and select data, you can, of course, get node-set or tree fragment values. When you go down to the single element or attribute level, however, all values are either strings or numbers.

The big question is “How does XSLT determine what the actual data type is?” In most programming languages, you define a variable of a certain type, and when you assign a value to that variable, that value is automatically assumed (or converted) to be of the variable’s data type. XSLT doesn’t have variables that operate that way because variables in XSLT aren’t typed, and they serve only as a container for a value, no matter what the type. Instead, values in XSLT have a data type. This data type is determined dynamically, and XSLT is therefore sometimes called a dynamically typed language.

The fact that XSLT is dynamically typed means that when you perform some operation on a value, the value gets the data type that is most likely to be the one you need. For instance, if you perform a string operation on a number, the number is converted to the string data type implicitly. You need to be careful with these conversions because some rules apply when this conversion happens. These rules will be discussed later in the “Conversion Between Data Types” section. Before you get into those details, it’s a good idea to look at the separate data types in XSLT.

The Boolean Data Type

The Boolean data type is a bit odd. A Boolean value can have one of two values, true or false, but these values don’t exist by themselves. By that, I mean that there is no value you can put in an XML source document or in a stylesheet that will represent either of these values directly. Instead, XSLT offers two functions: true () and false (). These functions can be used to compare the result of some expression with the Boolean values. This is different from other languages in which Boolean values do have representations that you can use instead of true or false. The most common is zero for false and nonzero for true.

The Boolean data type works in this odd way because it is basically only for internal use in XSLT. Its use is limited to expressions in which you need to actually compare with the actual value. Most of the time, you will have an expression that compares two values. This expression yields a Boolean value, which is used to do something or not. This comparison can basically occur in two separate scenarios:

• An expression in the test attribute of xsl:if or xsl:choose. This expression needs to return a Boolean value to determine whether the element body of these elements needs to be executed. For instance,

<xsl:if test="$id = @id">
    <xsl:value-of select="@name" />
</xsl:if>

• An expression in a predicate. This expression needs to return a Boolean value to determine whether the node being evaluated is to be part of the selection. For instance,

<xsl:value-of select="name[@id = $id]" />

When you compare two values, you can be faced with many surprises. They will be discussed later in the “Comparing Values” section.

The Number Data Type

A number is a number. Not much to say about it, is there? Well, actually, there is, because a number is not just a number. A number must conform to quite a few rules, which are necessary to define what happens in unusual cases, such as adding two 8-bit integers that yield a value higher than 255.

Fortunately, XSLT uses only one data type for numbers, instead of several. This means that there are no problems with conversion, and you don’t have to learn different sets of rules. Keep in mind that the rules of the number type in XSLT aren’t always straightforward, but if you get the general idea, you are already halfway home. So, don’t worry if you can’t understand all this information at once.

A number in XSLT is always treated as a double-precision 64-bit floating-point number. Its behavior follows ANSI/IEEE standard 754-1985, the IEEE Standard for Binary Floating-Point Arithmetic, which is also used in Java. The range that can be represented by these numbers is huge, and very specific rules define what happens in cases in which results are outside this range. However, in ordinary calculations, getting results outside this range is nearly impossible.

The IEEE 754-1985 standard defines six different “ranges” of values: finite non-zero, positive zero, negative zero, positive infinity, negative infinity, and Not a Number (NaN). Each of them is covered in detail in the following sections.

Finite Non-Zero Values

Finite non-zero values are those values that can be expressed explicitly with the memory space available (64 bits). Under this category fall all integer numbers within a certain range and fractional numbers with quite a few numbers after the decimal point. All values that can be expressed as finite non-zero numbers in IEEE 754-1985 can be expressed with the following formula:

s x m 2x

In this formula s is the sign (negative or positive), m the mantissa (a number between 1 and 253-1, inclusive), and x the exponent (which needs to be a number between -1,075 and 970, inclusive). Remembering all these details is not very important, but this formula means that the largest integer you can represent is 8.9885E307, or 89885 with 303 zeros. The largest negative integer is, of course, the opposite: -8.9885E307.

Note

The number 8.9885E307 is written in scientific notation, where the number after the E is the exponent. To get the actual number, you have to multiply the part in front of the E by 10 to the power of the given exponent. If the exponent is positive, the decimal point is pushed backward (making the number larger) with the number given by the exponent. If the exponent is negative, the decimal point is pushed forward (making the number smaller).

Caution

XSLT does not support scientific notation, so you have to write out numbers in full, both in front of and after the decimal point. Be aware that using numbers this way can take quite a bit more space than in other formats, so an XML file consisting of mainly large numbers can be quite large.

Positive Zero

The term positive zero looks kind of strange. Zero is zero, isn’t it? Obviously, it is not, which has to do with how very large and very small numbers are dealt with. A number is positive zero in the following cases:

• Subtracting a number from itself—for instance, 10 - 10.

• Dividing a very small positive number by a very large positive number, or dividing a very small negative number by a very large negative number. The values have to be so small or large that the result can no longer be represented as a finite non-zero number.

• Dividing any positive number by positive infinity.

Negative Zero

Negative zero, of course, is positive zero’s evil twin brother. You get this value in the following cases:

• Dividing a very small positive number by a very large negative number

• Dividing a very small negative number by a very large positive number

• Dividing any negative number by positive infinity

• Dividing any positive number by negative infinity

Negative zero cannot be written as a value directly. It can only be the result of an expression. If you need a variable to be negative zero, you can use the expression -0 to assign it to the variable. You need this value if you are doing computations in a stylesheet that shouldn’t yield negative zero. With this value, you can check whether the calculation is correct.

Caution

There is debate whether -0 means negative zero or subtraction from zero. In the latter case, the result of this expression would actually be positive zero. Although most processors use the former meaning, a processor may use the latter, giving you an undesired result. In that case, you can get negative zero by dividing 1 by negative infinity.

Positive and negative zero are required to make a distinction between operations that yield a positive or negative number that is too small to be expressed as a finite number. In those cases, these values act as approximations for the actual result. Because they are approximations, you may want to know if the result is an approximation of a negative or a positive number.

Positive Infinity

Positive infinity is used when numbers get so large they can no longer be represented as finite non-zero numbers. This happens in the following cases:

• Adding two very large positive numbers

• Multiplying two very large numbers, both positive or both negative

• Dividing any positive number by zero

Positive infinity cannot be written as a value directly. It can only be the result of an expression. If you need a variable to be positive infinity, you can use the expression 1 div 0, to assign it to the variable. As with negative zero, the most common use of this value is checking whether a computation is correct.

Note

Division by zero is considered an error in many programming languages. With any language conforming to the IEEE 754-1985 standard, it has a well-defined result, being positive infinity.

Negative Infinity

Where there’s a positive, there is, of course, also a negative. Negative infinity is the result of the following calculations:

• Adding two very large negative numbers

• Multiplying two very large numbers, of which one is positive and the other negative

• Dividing any negative number by zero

Negative infinity cannot be written as a value directly. It can only be the result of an expression. If you need a variable to be negative infinity, you can use the expression -1 div 0 to assign it to the variable. This value is also mostly used to check whether a computation is correct.

Not a Number (NaN)

With all the preceding types of values, what is the use for the Not a Number (NaN) value? It is used basically in two situations, one in which there is no applicable value and one in which you convert a value that cannot be evaluated as a number—for instance, the string abc. In most other languages, such a conversion results in an error, so you have to check whether the conversion yields a valid value. In XSLT the specification is such that a stylesheet will work as long as it and the XML source document are well formed and the XSLT syntax is correct. If conversion of an invalid string value to a number would result in an error, this aim cannot be met.

NaN cannot be written as a value directly. It can only be the result of an expression. If you need a variable to be NaN, you can use the expression number ("NaN") to assign it to the variable. This expression is covered in more detail in the section “Conversion Between Data Types.”

The String Data Type

For most programmers, the string data type is very familiar. A short description is in order, though. A string is a sequence of zero or more characters—no surprises there. Basically, these characters can be any Unicode characters, but with some exceptions.

A string written as a literal in an XPath expression needs to be surrounded by single or double quotation marks—for example, 'Michiel' or "Michiel". As you learned on Day 7, “Controlling the Output,” some characters need to be output escaped if you use a literal string (in an XPath expression). In some cases, however, you don’t need to; for instance, "Eat At Joe's" works fine because the double quotation marks are used as the string delimiters, so the single quotation mark can be used. The other way around also works—for instance, 'He said "hello"'.

Unicode contains several special characters (inherited from ASCII), called control characters. These characters are not supported by XSLT in any shape or form. They are leftovers from before the pretty user interfaces and stereo surround-sound cards. Many of these characters, such as the character denoting a sound beep, have no useful purpose anymore but are still part of the character set. The control characters that are supported are tab (#x9), carriage return (#xA), and new line (#xD); any other control characters are ignored by most parsers, but if not, may be the cause for errors.

The Node-set Data Type

The node-set data type is one of the types you are most familiar with from a theoretical standpoint because it was discussed thoroughly on Day 3, “Selecting Data.” I want to touch on some points again, however, because they are significant for the understanding of node-sets.

A node-set is a set, so theoretically the nodes in a node-set aren’t in any particular order. A document or XML fragment is, however, always processed in the order in which the elements appear in the source XML, which is called document order. This means that, in a practical sense, a node-set is ordered in document order.

A node-set contains only the nodes that match the expression used to create the node-set. Although their descendant elements are accessible from the node-set, they do not belong to the node-set itself. This, of course, also means that if you count the number of nodes in a node-set, only the nodes in the node-set itself are counted, not their descendant elements. So, the expression count (/) or count (/menu) used with Listing 10.1 yields 1 as a result. The expression count (/menu/entrees/dish) yields 5. Because node-sets don’t have to consist of nodes on the same level, with the same name, or even the same type, you can use axes to get other useful node-sets. For instance, if you want to know the depth of a certain node in the source document, you can use the expression count (ancestor-or-self::*). If the context node is any dish element in Listing 10.1, this expression yields 3 because the node-set consists of the dish element itself, the parent element, and the grandparent element menu.

LISTING 10.1 Sample XML

<?xml version=″“1.0”" encoding="UTF-8"?>
<menu>
  <appetizers title="Work up an Appetite">
    <dish id="1" price="8.95">Crab Cakes</dish>
    <dish id="2" price="9.95">Jumbo Prawns</dish>
    <dish id="3" price="10.95">Smoked Salmon and Avocado Quesadilla</dish>
    <dish id="4" price="6.95">Ceasar Salad</dish>
  </appetizers>
  <entrees title="Chow Time!">
    <dish id="5" price="19.95">Grilled Salmon</dish>
    <dish id="6" price="17.95">Seafood Pasta</dish>
    <dish id="7" price="16.95">Linguini al Pesto</dish>
    <dish id="8" price="18.95">Rack of Lamb</dish>
    <dish id="9" price="16.95">Ribs and Wings</dish>
  </entrees>
  <desserts title="To Top It Off">
    <dish id="10" price="6.95">Dame Blanche</dish>
    <dish id="11" price="5.95">Chocolat Mousse</dish>
    <dish id="12" price="6.95">Banana Split</dish>
  </desserts>
</menu>

Note

You can download the sample listings in this lesson from the publisher’s Web site.

One point to keep in mind is that there is no data type to represent a single node. A single node is therefore represented by a node-set containing the one node.

The Tree Fragment Data Type

When you first learned about tree fragments, you really had no way of creating one. You could create something that felt like one, but a tree fragment in itself cannot be created from just an expression. Tree fragments can exist only inside a variable or parameter, and then only when explicitly created as such. An example of a tree fragment created in a variable is shown in Listing 10.2.

LISTING 10.2 Tree Fragment in a Variable

1:  <xsl:variable name="tree">
2:    Canadian <athlete>sprinter</athlete> <person>John Benson</person>
3:    ran the <event>100 meters</event> in a new world record time of
4:    <time>4.98 seconds</time>.
5:  </xsl:variable>

ANALYSIS

You might be a little surprised that Listing 10.2 doesn’t have a root node. Line 2 just starts with text, and the value contains some elements as well. The whole value of the variable is mixed content from lines 2–4. For all practical purposes, the xsl:variable element acts as a root node. So, the text at the start of the fragment is, in fact, just a text node that is created under the root. A pitfall here is that because the variable acts as the root node, you may think that you can add attributes without first adding an element, as shown in Listing 10.3.

LISTING 10.3 Variable with Attributes

1:  <xsl:variable name="tree">
2:    <xsl:attribute name="title">New 100m World Record</xsl:attribute>
3:    Canadian <athlete>sprinter</athlete> <person>John Benson</person>
4:    ran the <event>100 meters</event> in a new world record time of
5:    <time>4.98 seconds</time>.
6:  </xsl:variable>

ANALYSIS

Line 2 in Listing 10.3 adds an attribute to the variable. Because there is no explicit element, this is illegal. A processor will report an error if the code in Listing 10.3 is used.

A tree fragment is useful only for storing data temporarily or passing it on to a template. When you want to display a tree fragment, you can just use xsl:value-of, but this approach concatenates all text in the tree fragment’s elements and displays it as a string. If you want to display the text otherwise, you have to apply some form of processing—for instance, with a template.

Conversion Between Data Types

Data types are useful to determine how an operation on a data value should be interpreted and what the resulting value should be. But what if the value you want to perform an operation on doesn’t have the data type you require? In that case, you can explicitly convert values to a certain data type so that you are sure that any operations performed on the value are executed correctly. In other cases, data type conversion may occur implicitly—for instance, when you compare two values of different types.

Explicit Data Type Conversion

XSLT offers three functions to explicitly convert a value from one data type into another. These functions—boolean (), number (), and string ()—convert the value given between the parentheses to the type corresponding to the function name, as in these examples:

boolean (5)

number ('1.23')

string (/menu/entrees)

Conversion from one data type to another is bound to very specific rules, so you always know what the outcome is. You can convert only to simple data types. You cannot convert a Boolean, number, or string value into a node-set or a tree fragment.

Conversion to Boolean

The rules surrounding conversion of values to the Boolean data type are relatively simple. They are shown in Table 10.1.

TABLE 10.1 Conversion to Boolean from Other Data Types

Image

As you can see in Table 10.1, determining the value of a conversion to Boolean is not hard. The only exception is the tree fragment, which is converted to a string first and then converted from a string to a Boolean. Basically, this means that if at least one nonempty text element exists in the tree fragment, the result is true. Listing 10.4 is a sample.

LISTING 10.4 Sample XML for Data Type Conversion

<?xml version=″“1.0”" encoding="UTF-8"?>
<cars>
  <car model="Focus" manufacturer="Ford" year="2000" />
  <car model="Golf" manufacturer="Volkswagen" year="1999" />
  <car model="Camry" manufacturer="Toyota" year="1999" />
  <car model="Civic" manufacturer="Honda" year="2000" />
  <car model="Prizm" manufacturer="Chevrolet" year="2000" />
</cars>

When you use the following expressions in a stylesheet that transforms Listing 10.4, they will all yield true:

boolean (/cars/car/@year)

boolean (/cars/car/@model)

boolean (/)

The following examples all yield false:

boolean (0)

boolean ('')

boolean (//cars[@manufacturer = 'Rolls Royce')

Conversion to Number

Conversion to a number is well defined when you’re working with string and Boolean values. For node-sets and tree fragments, the conversion becomes somewhat more difficult because these values have to be converted to strings first, as you can see in Table 10.2.

TABLE 10.2 Conversion to Number from Other Data Types

Image

When a tree fragment is converted to a string, all text nodes are concatenated. If that results in a string that can be parsed as a decimal number, you’re in business. Consider the variable containing a tree fragment in Listing 10.5.

LISTING 10.5 Variable Containing a Tree Fragment

<xsl:variable name="tree">
  123
  <decpoint>.</decpoint>
  <fraction>456</fraction>
</xsl:variable>

ANALYSIS

If the variable in Listing 10.5 is converted to a number, using number (tree), the resulting value is 123.456. If the tree fragment contains any character that has no place in a number, such as 'abc', the tree fragment yields a string that cannot be parsed as a number and therefore results in NaN.

Conversion to String

Conversion to string is very important because, as you learned previously, the string data type is used as an intermediate data type when converting node-sets and tree fragments to Boolean and number data types. The way these conversions behave is shown in Table 10.3.

TABLE 10.3 Conversion to String from Other Data Types

Image

Conversion to the string data type looks more complicated than it is. Boolean and number values are straightforward, but you need to be aware that if you have large number values or values with very many places after the decimal point, the text representation can easily span 200 characters. Values that are not finite have different text representations, as shown in Table 10.4.

TABLE 10.4 Number Conversions for Nonfinite Numbers to Strings

Image

Implicit Data Type Conversion

Implicit data type conversions happen when you compare two values or write values to the output. The rules employed by implicit conversions are the same as for explicit conversions. Understanding these rules is very important because you will likely be faced with them often when you’re creating expressions. Specifically, when you’re comparing values, you may be faced with some surprising results.

When you write a value to the output, it is always converted into a string, and the conversion rules for strings are as discussed in the preceding sections and shown in Tables 10.3 and 10.4.

Conversion Pitfalls

Because of the way the conversion rules are set up, you need to be aware of some pitfalls. One of the most common concerns conversion from one type to another and back again. For instance, if you write

boolean (string (false ())

the result is true instead of false because the inner expression yields the string false, which is not empty. When you convert back to Boolean, the nonempty string is regarded as true. This issue also is a concern when you convert between numbers and strings. For instance,

number (string (-1 div 0))

results in a number with the value NaN. The inner expression -1 div 0 results in negative infinity. However, when that result is converted to a string, the string value is -Infinity, which results in NaN when converted back to a number.

Comparing Values

Being able to compare values is one of the key operations in XSLT. It is crucial for selecting data and taking action based on certain values. When you compare two values of different types, one value is converted into another. This conversion is governed by the rules employed for explicit conversion, but other rules tell you which value is being converted and which stays the same. These rules can be summed up as follows:

• When you compare a string with a number, the string is converted to a number.

• When you compare a string with a Boolean, the string is converted to a Boolean.

• When you compare a number with a Boolean, the number is converted to a Boolean.

• When a node-set or tree fragment is compared with a simple data type, the node-set or tree fragment is converted to that simple type.

• You cannot compare a node-set with a tree fragment.

From the preceding list, you can gather that when two values of different types are compared, the most basic data type is the one that stays the same. The other is converted. The only thing you have to remember is which data type is most basic. In sequence, they are as follows, from most basic to least basic:

• Boolean

• Number

• String

• Node-set/tree fragment

You can, of course, get around these rules by converting explicitly before comparing the values. This approach, however, is not applicable in many cases. It is useful only if you have two node-sets or tree fragments that you do not want to compare as such. For instance, if you want to check whether appetizers and desserts are in the menu in Listing10.1, you must write the expression as follows:

boolean (//appetizers/dish) = boolean (//desserts/dish)

If there are appetizers and desserts, this expression returns true. If you write

//appetizers/dish = //desserts/dish

the two node-sets are compared, obviously resulting in false.

Comparison Pitfalls

You might think that comparing numbers is straightforward because numbers are so well defined. As long as you compare finite numbers, there is no problem. They are seen as the same when their values are the same. The number definition, however, does have some strange values apart from finite numbers. Some of them behave as you would expect; others don’t.

When you’re dealing with NaN values, you should be aware that, even if values were created from the same expression, comparing them still yields false. So, if you have a variable x containing a NaN value, the expression $x = $x results in false.

On the other hand, when you’re working with positive and negative infinity, the values are regarded as the same as long as the sign is the same, even if they result from the same expression. So, the expression 1 div 0 = 2 div 0 results in true.

The last special case is zero. Positive and negative zero are regarded as the same, no matter the sign. So -0 = 0 results in true.

Number comparison can be quite tricky, and it doesn’t end there. Empty values, in particular, can wreak havoc in your stylesheet, as you can see from the following two examples:

boolean (@manufacturer = 'Rolls Royce')

boolean (@manufacturer != ' Rolls Royce ')

In Listing 10.4, there is no manufacturer named Rolls Royce, so one example returns true and the other false, right? Wrong, both return false.

Summary

Today you were bombarded with information regarding data types. Don’t worry if you didn’t understand it all. When you put to practice all that you have learned in this book (and all you will learn in the coming lessons), you will be reminded of some of the things you learned here when you get results that you didn’t expect. Only through practice will you truly get a feel for these sorts of issues. If you stick to the basics, though, you may get very far, so I’ll recap them.

XSLT has five data types; ordered from least complex to most complex, they are

• Boolean

• Number

• String

• Node-set

• Tree fragment

When values of different types are compared or used in some other operation, the value of the most complex type is converted to the value that has the least complex type. The number type is treated as a double-precision floating-point, as defined in ANSI/IEEE standard 754-1985. Although this is a well-defined standard, some odd behaviors have their roots in how this definition works. These behaviors will be obvious only when you lurk around the edges, working with numbers that are so huge or so small that they can’t be expressed as finite numbers. As soon as you go into the shadows of infinity and NaN values, you’re pretty much Alice in Wonderland, so expect the unexpected.

Some odd behavior can also be seen without numbers. Double conversions and comparisons with nonexisting values also give rise to unexpected results. If you truly understand everything in this lesson, you will always be able to solve the problems quickly. Otherwise, you may have a hard time.

Note

Many forums and mailing lists can help you when intricate details are important. Somebody else may spot a nuance that you overlooked or wasn’t aware of. Such resources have helped me many times. Appendix D contains a list of helpful Web sites and mailing lists.

Tomorrow you will learn more details about the practical side of data types. In tomorrow’s lesson, you will learn about functions that can be used to manipulate string values. They often can be used to get around the limitations of data types.

Q&A

Q Why can’t I convert a simple data type to a node-set or tree fragment?

A Converting such a data type wouldn’t make much sense. The best you can do is create a single node with the value, but then it would basically remain a simple type.

Q Why would I want to convert a Boolean to a string?

A I grant that you won’t do this conversion often; however, you may need it when you’re creating documents that contain very specific data—for certain calculations, for instance. You also can use this conversion to store their values in a document so that you can later read them back and make a string comparison to determine their Boolean value, such as x = 'true'.

Q Isn’t there a Null value in XSLT, like in SQL or C++?

A No. There is no need for one. NaN and empty strings are used instead. Boolean values can only exist from expressions. Because the results are well defined, the Boolean type doesn’t need a Null value.

Q I use very large numbers in my source XML. Can’t I write them in scientific notation?

A You could create a template to dissect and convert the values into numbers. This topic will be covered in tomorrow’s lesson.

Workshop

This workshop tests whether you understand all the concepts you learned today. It is very helpful to know and understand the answers before starting tomorrow’s lesson. You can find the answers to the quiz questions and exercises in Appendix A.

Quiz

1. True or False: A node-set value can be converted to a Boolean value.

2. True or False: Comparing two values always yields a Boolean value.

3. Why do you need positive zero and negative zero?

4. When positive and negative zero are compared, they are the same. Why?

5. How can you check whether a number has an NaN value?

Exercise

1. Create a stylesheet that performs conversions and double conversions (back to the original data type on the values in the following XML document). Display the data type that was specified by the element name. Bonus: Compare values such as 1 div 0 and 2 div 0.

<?xml version=″“1.0”" encoding="UTF-8"?>
<datatypes>
  <number>123</number>
  <number>0</number>
  <number>-0</number>
  <number>Infinity</number>
  <number>-Infinity</number>
  <number>NaN</number>
  <number>xyz</number>
  <number></number>
  <boolean>123</boolean>
  <boolean>0</boolean>
  <boolean>true</boolean>
  <boolean>false</boolean>
  <boolean>xyz</boolean>
  <boolean></boolean>
  <string>xyz</string>
  <string></string>
  <string>123</string>
</datatypes>

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.14.245