Working on Strings

This chapter is all about the XPath 2.0 string functions. XPath 2.0 now includes support for regular expressions , which let you match strings and work with the text in them, as we'll see in this chapter.

The functions in this chapter work on operands of type xs:string and types derived from xs:string. There are a number of general-purpose functions that work on strings in XPath 2.0, and we'll begin with them:

  • fn:compare compares two or more strings.

  • fn:concat joins two or more strings.

  • fn: string-join joins strings using an optional separator.

  • fn: starts-with returns true if a string begins with a specified start string.

  • fn: ends-with returns true if a string ends with a specified end string.

  • fn:contains returns true if one string contains a specified string.

  • fn:substring extracts the substring located at a specified location in a string.

  • fn: string-length returns the length of a string.

  • fn: substring-before returns the characters of one string that come before a match with another string.

  • fn:substring-after returns the characters of one string that come after a match with another string.

  • fn:normalize-space returns the whitespace-normalized value of a string.

  • fn: normalize-unicode returns the normalized value of a string using a specified Unicode normalization form.

  • fn: upper-case returns the value of an uppercased string.

  • fn: lower-case returns the value of a lowercased string.

  • fn:translate returns a string with occurrences of characters in a map string replaced by the character at the corresponding position in a translate string.

  • fn: escape-uri returns the xs:anyURI value represented as a string with certain characters escaped.

We'll take a look at these functions now.

The fn:compare Function

You can use the fn:compare function to compare two xs:strings ; here are the two possible ways to use this function:

 
 fn:compare($  operand1  as xs:string?, $  operand2  as xs:string?) as xs:integer? fn:compare($  operand1  as xs:string?, $  operand2  as xs:string?,     $  collation  as xs:string) as xs:integer? 

This function returns 1, 0, or 1, depending on whether the value of $operand1 is less than, equal to, or greater than the value of $operand2 :

  • $operand1 is less than $operand2 .

  • $operand1 is equal to $operand2 .

  • 1 $operand1 is greater than $operand2 .

If the value of $operand2 begins with a string that is equal to the value of $operand1 and has additional characters following that beginning string, the result is 1. If the value of $operand1 begins with a string that is equal to the value of $operand2 and has additional characters following that beginning string, the result is 1. As you might expect, if either argument is the empty sequence, the result is the empty sequence.

Here's an example; in this case, we'll compare two strings, "bcdef" and "abcdef"; the first of these is greater than the second in string terms. If the comparison yields a value greater than 0, we know that string 1 is greater than string 2:

 
 <xsl:value-of select="if(compare('bcdef', 'abcdef') > 0)     then 'String 1 is greater than String 2' . . . 

Otherwise , we know that string 2 is less than or equal to string 1, as you can see in ch10_01.xsl (Listing 10.1).

Listing 10.1 An XSLT Example Using the XPath Function fn:compare ( ch10_01.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">     <xsl:template match="/">         <xsl:value-of select="if(compare('bcdef', 'abcdef') > 0)             then 'String 1 is greater than String 2'  else 'String 2 is less than or equal to String 1' "/>  </xsl:template> </xsl:stylesheet> 

And here's the result you get when you use this stylesheet:

 
 <?xml version="1.0" encoding="UTF-8"?> String 1 is greater than String 2 

The second form of the fn:compare function introduces us to the idea of collations , which let you specify the order in which comparisons are madenote the $collation value:

 
 fn:compare($  operand1  as xs:string?, $  operand2  as xs:string?,     $  collation  as xs:string) as xs:integer? 

$collation holds the name of a collation, which indicates the collation you want to use to compare the strings. That's as far as the XPath 2.0 specification goes in letting you indicate what collation to use. Connecting a named collation to the code that implements it is up to the implementation.

MORE ON COLLATIONS

Some programming languages let you define your own collations using functions. XPath 2.0 does not support that, although some such provision might be made in the future. At this point, XPath 2.0 only supports implementation-dependent named collations. Collations are named by URIs; that is, functions that allow specification of a collation use an argument whose type is xs:string but whose lexical representation is xs:anyURI .


Collations are useful when you need a different comparison order, as might be needed in different languages. For example, in some collations, the words "Jaeger" and "J ger" might be treated as equal. If you don't specify a collation to be used, the standard default collation is used, called the Unicode codepoint collation, whose name is "http://www.w3.org/2003/05/xpath-functions/collation/codepoint".

USING xml:lang

Although you can use XML to specify a value for the xml:lang attribute, setting the default language for the document, XPath 2.0 does not instruct XPath 2.0 processors to use that attribute in determining the collation. Instead, it regards setting the collation as up to you.


Here's an example that uses a fictitious collation named "http://XPathCorp/german" that may be supported by some XPath 2.0 implementation that will consider the words "Musse" and "Mu e" as equal (in German, is a special character that corresponds to using two s characters). Here's how you might make that comparison:

 
 \fn:compare("Musse", "Mue", "http://XPathCorp/german") 

In this case, this comparison would yield 0. Only default comparisons are supported in Saxon at this time, so we won't deal with special named collations here.

The fn:concat Function

You use the fn:concat function to concatenate strings; here is the signature:

 
 fn:concat(  $operand1  as xs:string?,  $operand2  as xs:string?, ...) as xs:string 

This function is designed to accept two or more xs:string values as arguments, and returns the concatenation of the arguments you pass to it as an xs:string . In other words, you can pass this function an arbitrary number of string arguments, and it will join them together for you.

VARIABLE NUMBERS OF ARGUMENTS

Actually, fn:concat is the only XPath 2.0 function that can take a variable number of arguments. And that was only allowed for the sake of compatibility with XPath 1.0. In XPath 2.0, you can pass a variable number of arguments to many functions, but they have to be in a sequence.


Here are some examples:

 
 fn:concat('Now is ', 'the time.') returns "Now is the time.". fn:concat('Now ', 'is ', 'the ', 'time.') returns "Now is the time.". 

We've already used this function in both XPath 1.0 and 2.0; here's an example from the preceding chapter, ch09_12.xsl , where we used this function to assemble a string:

 
 <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> 

This is a good one to know, and it's handy because it allows you to pass multiple strings to it. As in XPath 1.0, you'll probably find yourself working with this one a lot.

The fn:string-join Function

This function is much like fn:concat , except that it joins strings using a separator that you specify. Here's what its signature looks like (recall that the * symbol indicates a sequence):

 
 fn:string-join(  $operand1  as xs:string*,  $operand2  as xs:string) as xs:string 

For instance, we just saw this example in the preceding sectionnote that we had to explicitly include spaces in each string to be concatenated to make the final string come out right:

 
 fn:concat('Now ', 'is ', 'the ', 'time.') returns "Now is the time.". 

On the other hand, if you use a space character, " ", as a separator, you don't need to add that space to each string to be concatenated:

 
 fn:string-join(('Now', 'is', 'the', 'time.'), " ") returns "Now is the time.". 

This function is useful if you want to create comma-separated lists, as you can see in ch10_02.xsl (Listing 10.2), where we're creating such a list of the planets in our planetary data document.

PASSING AN EMPTY STRING

If you pass an empty string, "" , as the separator to this function, this function works much the same as the fn:concat function.


Listing 10.2 An XSLT Example Using the XPath Function fn:string-join ( ch10_02.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">     <xsl:template match="/">  <xsl:value-of select="string-join(//planet/name, ', ')"/>  </xsl:template> </xsl:stylesheet> 

Here's what you see when you run this example through Saxon:

 
 C:\Saxon>java net.sf.saxon.Transform ch02_01.xml ch10_02.xsl <?xml version="1.0" encoding="UTF-8"?> Mercury, Venus, Earth 

The fn:starts-with Function

As you can guess from its name, the fn:starts-with function lets you check whether one string starts with another. Here are the possible signatures for this function:

 
 fn:starts-with(  $operand1  as xs:string?,  $operand2  as xs:string?) as xs:boolean? fn:starts-with(  $operand1  as xs:string?,  $operand2  as xs:string?,  $collation  as xs:string) as xs:boolean? 

This function returns an xs:boolean value indicating whether or not the value of $operand1 starts with a string that is equal to the value of $operand2 according to the collation that is used.

You can see an example in ch10_03.xsl (Listing 10.3), where we're confirming that the string "Steven" does indeed start with the string "Steve".

Listing 10.3 An XSLT Example Using the XPath Function fn:starts-with ( ch10_03.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:xs="http://www.w3.org/2001/XMLSchema">     <xsl:template match="/">  <xsl:value-of select="if(starts-with('Steve', 'Steve'))   then 'Hi Steve!'   else 'Hi there.'"/>  </xsl:template> </xsl:stylesheet> 

Here is the result you get from Saxon:

 
 <?xml version="1.0" encoding="UTF-8"?> Hi Steve! 

Here are a few more examples:

 
 fn:starts-with("lemonade", "lemon") returns true. fn:starts-with("lemonade", "onade") returns false. fn:starts-with("lemonade", "") returns true. 

The fn:ends-with Function

This function is the counterpart of fn:starts-with , but this one tests whether one string ends with another string. Here are the two ways to use this function:

 
 fn:ends-with(  $operand1  as xs:string?,  $operand2  as xs:string?) as xs:boolean? fn:ends-with(  $operand1  as xs:string?,  $operand2  as xs:string?,  $collation  as xs:string) as xs:boolean? 

This function returns an xs:boolean value indicating whether or not the value of $operand1 ends with a string that is equal to the value of $operand2 .

You can see an example in ch10_04.xsl (Listing 10.4), where we're confirming that the string "Red car" ends with the string "car".

Listing 10.4 An XSLT Example Using the XPath Function fn:ends-with ( ch10_04.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:xs="http://www.w3.org/2001/XMLSchema">     <xsl:template match="/">  <xsl:value-of select="if(ends-with('Red car', 'car'))   then 'That is a car.'   else 'That is not a car.'"/>  </xsl:template> </xsl:stylesheet> 

Here are the results you get when you run this example through Saxon:

 
 <?xml version="1.0" encoding="UTF-8"?> That is a car. 

And here are a few more examples:

 
 fn:ends-with("Cary Grant", "ant") returns true. fn:ends-with("Cary Grant", "ent") returns false. 

The fn:contains Function

This function checks to see whether one string contains another. The two forms of this function look like this:

 
 fn:contains(  $operand1  as xs:string?,  $operand2  as xs:string?) as xs:boolean? fn:contains(  $operand1  as xs:string?,  $operand2  as xs:string?,  $collation  as xs:string) as xs:boolean? 

The fn:contains function returns true if $operand1 contains $operand2 , and false otherwise.

Here's an example; in this case, we're scanning some text for nasty words, as you can see in ch10_05.xsl (Listing 10.5).

Listing 10.5 An XSLT Example Using the XPath Function fn:contains ( ch10_05.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:xs="http://www.w3.org/2001/XMLSchema">     <xsl:template match="/">  <xsl:value-of select="if(contains('That darn George!', 'darn'))   then 'Don''t use nasty words!'   else 'That text was OK.'"/>  </xsl:template> </xsl:stylesheet> 

And here's what you get when you run this example through Saxon:

 
 <?xml version="1.0" encoding="UTF-8"?> Don't use nasty words! 

The fn:substring Function

The fn:substring function lets you extract a substring from another string. Here are the two ways to use this function:

 
 fn:substring(  $sourceString  as xs:string?,  $startPosition  as xs:double) as xs:string? fn:substring(  $sourceString  as xs:string?,  $startPosition  as xs:double,  $length  as xs:double) as xs:string? 

The first version of this function lets you pass a string to it and a starting position (the beginning of the string corresponds to position 1), and it returns the substring that starts at the starting position in the string and ends at the end of the string.

The second version of this function accepts a string, a starting position, and a length, and returns the same string as the first version of the function, except that the returned string is truncated to be the specified length.

Here are a few examplesnote that the numbers you pass to this function are rounded if they are not integers:

 
 fn:substring("Now is the time", 2) returns "ow is the time". fn:substring("This is Chapter 10.", 2, 3) returns "his". fn:substring("This is Chapter 10.", 1.6, 2.9) returns "his". 

You can see an example in an XSLT 2.0 stylesheet in ch10_06.xsl (as shown in Listing 10.6), where we're extracting a string from the string "Now is the time." using XSLT variables . In this case, we just want to extract the substring "time".

Listing 10.6 An XSLT Example Using the XPath Function fn:substring ( ch10_06.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:xs="http://www.w3.org/2001/XMLSchema">     <xsl:variable name="start" select="12" />     <xsl:variable name="length" select="4" />  <xsl:template match="/">   <xsl:value-of select="substring('Now is the time', $start, $length)"/>   </xsl:template>  </xsl:stylesheet> 

And here's what you see when you run this through Saxon:

 
 <?xml version="1.0" encoding="UTF-8"?> time 

This function is a good one to use when the data in an XML document you're using contains text that you have to extract substrings from, for example, when what should be single records are stored together in longer strings.

The fn:string-length Function

As you can guess from this function's name, it returns the length of a string. There are two ways to use this function, as you can see here:

 
 fn:string-length(  $operand  as xs:string?) as xs:integer? fn:string-length() as xs:integer? 

Usually, you pass a string to this function, which returns the string's length in characters. If you don't pass a string to this function, it returns the string length of the context item (that is, .).

Here's an example; in this case, we're checking the relative lengths of two strings, "Now is the time!" and "No worries!". First, we store those lengths in two XSLT variables:

 
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:xs="http://www.w3.org/2001/XMLSchema">  <xsl:variable name="length1" select="string-length('Now is the time!')" />   <xsl:variable name="length2" select="string-length('No worries!')" />  .         .         . 

Then we compare those lengths using two nested XPath 2.0 if expressions, as you can see in ch10_07.xsl (Listing 10.7). These if expressions return various messages depending on the comparison: "The first string is longer.", "The second string is longer.", or "The strings have the same length."

Listing 10.7 An XSLT Example Using the XPath Function fn:string-length ( ch10_07.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:xs="http://www.w3.org/2001/XMLSchema">     <xsl:variable name="length1" select="string-length('Now is the time!')" />     <xsl:variable name="length2" select="string-length('No worries!')" />     <xsl:template match="/">  <xsl:value-of select="if($length1 > $length2)   then 'The first string is longer.'   else if ($length2 > $length1)   then 'The second string is longer.'   else 'The strings have the same length.'"/>  </xsl:template> </xsl:stylesheet> 

In this case, we're comparing "Now is the time!" and "No worries!", so as you'd expect, you get this result from Saxon:

 
 <?xml version="1.0" encoding="UTF-8"?> The first string is longer. 

The fn:substring-before Function

This function returns the substring that comes before a matched substring in another string. Here are the two ways to use this function:

 
 fn:substring-before(  $operand1  as xs:string?,  $operand2  as xs:string?) as xs:string? fn:substring-before(  $operand1  as xs:string?,  $operand2  as xs:string?,  $collation  as xs:string) as xs:string? 

Here, $operand1 is the string you want to work with, and $operand2 holds the substring you want to match in $operand1 . This function returns the substring in $operand1 that precedes the first complete match to the text in $operand2 . Note that if $operand1 does not contain $operand2 , this function returns an empty string, "" .

Here are a few examples:

 
 fn:substring-before("No worries","wo") returns "No ". fn:substring-before("No worries","o") returns "N". fn:substring-before("No worries","") returns "No worries". 

The fn:substring-after Function

The fn:substring-after function works just as the fn:substring-before function works, except that it returns the substring that comes after the match, not before. Here are the two ways to use this function:

 
 fn:substring-after($operand1 as xs:string?,     $operand2 as xs:string?) as xs:string? fn:substring-after($operand1 as xs:string?, $operand2  as xs:string?,  $collation  as xs:string) as xs:string? 

As with the fn:substring-before function, $operand1 is the string you want to work with, and $operand2 holds the substring you want to match in $operand1 . In this case, this function returns the text in $operand1 that follows the first complete match to the text in $operand2 . If $operand1 does not contain $operand2 , this function returns an empty string, "" .

You can see an example in ch10_08.xml (Listing 10.8), where we're extracting the substring that follows the first space in the string "No worries!".

Listing 10.8 An XSLT Example Using the XPath Function fn:substring-after ( ch10_08.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:xs="http://www.w3.org/2001/XMLSchema">     <xsl:template match="/">  <xsl:value-of select="substring-after('No worries!', ' ')"/>  </xsl:template> </xsl:stylesheet> 

And here's the result when you use Saxon:

 
 <?xml version="1.0" encoding="UTF-8"?> worries! 

Here are a few more examples:

 
 fn:substring-after("No worries!", "w") returns "orries!". fn:substring-after("No worries!", "lorries") returns "". fn:substring-after("No worries!", "") returns "". 

The fn:normalize-space Function

The fn:normalize-space function lets you normalizein XML termsthe whitespace in a string. Here are the two ways to use this function:

 
 fn:normalize-space(  $srcval  as xs:string?) as xs:string? fn:normalize-space() as xs:string? 

This function is designed to return $srcval with whitespace normalized by stripping leading and trailing whitespace and replacing sequences of more than one whitespace character by a single space. (In XML, whitespace includes not just spaces, but carriage returns, tabs, line feeds, and so on.) Note that if you don't pass an argument, this function uses the string value of the context item (.).

In this example, ch10_09.xsl , we'll normalize the text "No worries!", which should result in the text "No worries!". You can see how this works in Listing 10.9.

Listing 10.9 An XSLT Example Using the XPath Function fn:normalize-space ( ch10_09.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:xs="http://www.w3.org/2001/XMLSchema">     <xsl:template match="/">  <xsl:value-of select="normalize-space('No     worries!')"/>  </xsl:template> </xsl:stylesheet> 

And here's what Saxon gives you when you run this example:

 
 <?xml version="1.0" encoding="UTF-8"?> No worries! 

SHOP TALK : NORMALIZED OR NOT?

Normalization is a somewhat tricky issue in XPath 2.0. Ideally, W3C says that strings should be normalized before you work on them. However, they acknowledge that it's not possible to guarantee that all strings in the postvalidation stage are normalized.

In my experience, whether or not strings are normalized depends on the XML processor you're usingsome normalize strings automatically, some don't.

How various collations work with unnormalized strings is not definedit's implementation-defined. XPath 2.0 allows collations that operate on unnormalized strings, and you can also have collations that cause errors when unnormalized strings are used.

For that reason, I always watch out for this issue when working with a new XML processor. If you're working with an XSLT processor, it's easy to display the results of any validation, and you can see whether string normalization has occurred.

The XPath 2.0 specifications even allow for collations that normalize strings for the purposes of collating them, although there are no implementations that I know of yet.


The fn:normalize-unicode Function

This function lets you normalize text according to Unicode normalization forms; you can read all about these forms at http://www.unicode.org/ reports /tr15/. Here are the two ways to use this function:

 
 fn:normalize-unicode(  $srcval  as xs:string?) as xs:string? fn:normalize-unicode(  $srcval  as xs:string?,  $normalizationForm  as xs:string) as xs:string? 

This function returns the value of $srcval normalized according to the normalization form identified by the value of $normalizationForm . Here are the possibilities:

  • "NFC" means the function will use Unicode Normalization Form C (NFC).

  • "NFD" means the function will use Unicode Normalization Form D (NFD).

  • "NFKC" means the function will use Unicode Normalization Form KC (NFKC).

  • "NFKD" means the function will use Unicode Normalization Form KD (NFKD).

  • "Fully normalized" means that the value returned by the function is the value of $srcval in the fully normalized form.

  • If no normalization form is specified, it will be assumed to be "NFC".

The fn:upper-case Function

The fn:upper-case function, as you can tell from its name, converts strings to uppercase. Here's how you use it:

 
 fn:upper-case(  $srcval  as xs:string?) as xs:string? 

This function converts the string you send to it to uppercase. Note that not every character has an uppercase version (for example, "2"), and those that don't are returned in their original version.

You can see a quick example in ch10_10.xsl (Listing 10.10), where we're capitalizing the text "I said, 'No thanks.'" using this function.

Listing 10.10 An XSLT Example Using the XPath Function fn:upper-case ( ch10_10.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:xs="http://www.w3.org/2001/XMLSchema">     <xsl:template match="/">  <xsl:value-of select="upper-case('I said, ''No thanks.''')"/>  </xsl:template> </xsl:stylesheet> 

And here are the results:

 
 <?xml version="1.0" encoding="UTF-8"?> I SAID, 'NO THANKS.' 

The fn:lower-case Function

This function is the counterpart of the fn:upper-case function, and it converts a string to lowercase. Here's how you use this function:

 
 fn:lower-case($srcval as xs:string?) as xs:string? 

Not all characters have a lowercase version; if a character does not, the original version of the character is returned.

Here are a few examples:

 
 fn:lower-case("This is an example!") returns "this is an example!" fn:lower-case("This is NOT a test. 1-2-3-4-5.") returns     "this is not a test. 1-2-3-4-5." 

The fn:translate Function

The fn:translate function lets you translate text, character by character, into other text. Here's how you use this function:

 
 fn:translate(  $srcval  as xs:string?,  $mapString  as xs:string?,  $translationString  as xs:string?) as xs:string? 

This function performs a character-by-character translation. You pass it a source string to translate, a string of characters to match, and a string of characters to translate the matched characters to. Each character in the source string that matches a character in the match string is replaced by the character in the same position in the translation string.

For example, say you want to convert the text "hello!" to uppercase, and had temporarily forgotten about the fn:upper-case function. In this case, you start by passing this text to the fn:translate function:

 
 <xsl:template match="/">  <xsl:value-of select="translate('hello!',   .   .   .  </xsl:template> 

For every lowercase character, you want to supply an uppercase equivalent, so you start by matching every lowercase character this way:

 
 <xsl:template match="/">     <xsl:value-of select="translate('hello!',  'abcdefghijklmnopqrstuvwxyz',  .     .     . </xsl:template> 

When a lowercase character is matched, you can translate it to the corresponding character in the translation string you pass to this function, as you see in ch10_11.xsl in Listing 10.11.

Listing 10.11 An XSLT Example Using the XPath Function fn:translate ( ch10_11.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:xs="http://www.w3.org/2001/XMLSchema">     <xsl:template match="/">  <xsl:value-of select="translate('hello!',   'abcdefghijklmnopqrstuvwxyz',   'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>  </xsl:template> </xsl:stylesheet> 

Now when a lowercase character is found in the string you're translating, the corresponding uppercase character will be used instead. Here's the result:

 
 <?xml version="1.0" encoding="UTF-8"?> HELLO! 

As you can see, this function works on text character by character, so it's not as useful as, say, a text-replacing function.

Note also that if you don't provide a translated version of a character in the translation string, that character is omitted in the result. Here's an example:

 
 fn:translate("xyz", "xyz", "XY") returns "XY". 

If the translation string doesn't include a translation character for a character in the input string (that is, if the translation string is too short to include all characters you're translating), that character is simply omitted in the output.

The fn:escape-uri Function

This function is designed to "escape" URIs to convert the characters in them to a form more palatable to XML and browsers by converting sensitive characters to their simplified Unicode (UTF-8) equivalents. Here's this function's signature:

 
 fn:escape-uri(  $uri  as string,  $escape-reserved  as xs:boolean) as xs:string 

To use this function, you pass the URI to escape and an xs:boolean value named $escape-reserved .

If $escape-reserved is true, all characters are escaped except for lowercase letters, az; uppercase letters , AZ; the digits 09; and the characters "-", "_", ".", "!", "~", "*", "'", "(", and ")". The "%" character is also escaped if it is not followed by two hexadecimal digits.

On the other hand, if $escape-reserved is false, only these characters are escaped: " ", ";", "?", ":", "@", "&", "=", "+", "$", ",", "#", "[", "]".

For example, say that you have the URI http://www.XPathCorp/My Web Page.html , which has spaces in it that are problematic to use in a Web browser. You can escape the space characters in the URI with %20 character sequences using fn:escape-uri .

In this case, we don't want every possible character to be escaped, so we set $escape-reserved to false (using the Boolean function fn:false() ). You can see what this looks like in ch10_12.xsl (Listing 10.12).

Listing 10.12 An XSLT Example Using the XPath Function fn:escape-uri ( ch10_12.xsl )
 <xsl:stylesheet version="2.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:xs="http://www.w3.org/2001/XMLSchema">     <xsl:template match="/">  <xsl:value-of select="escape-uri(   'http://www.XPathCorp/My Web Page.html', false())"/>  </xsl:template> </xsl:stylesheet> 

And here's the result, where you see that the URI was properly escaped and is ready to be used in a browser:

 
 <?xml version="1.0" encoding="UTF-8"?> http://www.XPathCorp/My%20Web%20Page.html 


XPath. Navigating XML with XPath 1.0 and 2.0 Kick Start
XPath Kick Start: Navigating XML with XPath 1.0 and 2.0
ISBN: 0672324113
EAN: 2147483647
Year: 2002
Pages: 131

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net