<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY  quot	"&#x0022;"><!--	# QUOTATION MARK -->
<!ENTITY  ldquo	"&#x201C;"><!--	# LEFT DOUBLE QUOTATION MARK -->
<!ENTITY thisFile SYSTEM "ndata.txt" NDATA txt>
<!ELEMENT dp:lnk EMPTY>
<!ATTLIST dp:lnk idref IDREF #IMPLIED>
<!ATTLIST title id ID #IMPLIED>
<!ATTLIST ul id ID #IMPLIED>

]>

 

<xsl:stylesheet 
  id="StylesheetID"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:d="rnib.org.uk/tbs#" 
  xmlns:pref="http://www.dpawson.co.uk"
  xmlns:saxon="http://saxon.sf.net/"
  xmlns:dp="http://www.dpawson.co.uk/ns#"
  xmlns:xdt="http://www.w3.org/2005/02/xpath-datatypes"

  exclude-result-prefixes="xsl  xs dp pref saxon d"
                version="2.0"
  xpath-default-namespace=""
  xml:lang="en-UK"
>
<xsl:param name="debug" select="0" as="xs:integer"/>
<d:doc >
 <revhistory>
   <purpose><para>Test Harness for XSLT and xpath 2 constructs</para></purpose>
   <revision>
    <revnumber>1.3</revnumber>
    <date>17 April 2003</date>
    <authorinitials>DaveP</authorinitials>
    <revdescription>
     <para></para>
    </revdescription>
    <revremark></revremark>
   </revision>
 <revision>
    <revnumber>1.4</revnumber>
    <date>24 April 2003</date>
    <authorinitials>DaveP</authorinitials>
    <revdescription>
     <para>Added function-available list.</para>
    </revdescription>
    <revremark></revremark>
   </revision>

 <revision>
    <revnumber>1.5</revnumber>
    <date>11 May 2003</date>
    <authorinitials>DaveP</authorinitials>
    <revdescription>
     <para>Updated to May WD.</para>
    </revdescription>
    <revremark></revremark>
   </revision>

   <revision>
    <revnumber>1.6</revnumber>
    <date>11 June 2003</date>
    <authorinitials>DaveP</authorinitials>
    <revdescription>
     <para>Updated to Saxon 7.5.1.</para>
    </revdescription>
    <revremark></revremark>
   </revision>
   <revision>
    <revnumber>1.7</revnumber>
    <date>19 June 2003</date>
    <authorinitials>DaveP</authorinitials>
    <revdescription>
     <para>Corrections: + types (casts) added. </para>
    </revdescription>
    <revremark></revremark>
   </revision>
   <revision>
    <revnumber>1.8</revnumber>
    <date>24 June 2003</date>
    <authorinitials>DaveP</authorinitials>
    <revdescription>
      <para>Updated for Saxon 7.6</para>
    </revdescription>
    <revremark></revremark>
   </revision>

 <revision>
    <revnumber>1.9</revnumber>
    <date>8 July 2003</date>
    <authorinitials>DaveP</authorinitials>
    <revdescription>
      <para>Minor additions on sequences and types.</para>
    </revdescription>
    <revremark></revremark>
   </revision>

 <revision>
    <revnumber>1.10</revnumber>
    <date>10 Dec 2003</date>
    <authorinitials>DaveP</authorinitials>
    <revdescription>
      <para>Minor additions on namespaces etc.</para>
    </revdescription>
    <revremark></revremark>
   </revision>

 <revision>
    <revnumber>1.11</revnumber>
    <date>7 Jan 2004</date>
    <authorinitials>DaveP</authorinitials>
    <revdescription>
      <para>Removed 4 items no longer supported.</para>
    </revdescription>
    <revremark></revremark>
   </revision>

   <revision>
     <revnumber>1.12</revnumber>
     <date>13 Jan 2004</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Added data().</para>
     </revdescription>
    <revremark></revremark>
  </revision>
  
   <revision>
     <revnumber>1.13</revnumber>
     <date>1 Feb 2004</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Added element() type.</para>
     </revdescription>
    <revremark></revremark>
  </revision>
  

   <revision>
     <revnumber>1.14</revnumber>
     <date>7 Apr 2004</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Added base-uri() usage from Jeni. </para>
     </revdescription>
    <revremark></revremark>
  </revision>

   <revision>
     <revnumber>1.15</revnumber>
     <date>26 Apr 2004</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Added xsl:number example </para>
     </revdescription>
    <revremark></revremark>
  </revision>

   <revision>
     <revnumber>1.16</revnumber>
     <date>28 May 2004</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Added mode= #all </para>
     </revdescription>
    <revremark></revremark>
  </revision>

   <revision>
     <revnumber>1.17</revnumber>
     <date>23 Aug 2004</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Rebuild </para>
     </revdescription>
    <revremark></revremark>
  </revision>

  <revision>
     <revnumber>1.18</revnumber>
     <date>4 Aug 2004</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Added set section </para>
     </revdescription>
    <revremark></revremark>
  </revision>

  <revision>
     <revnumber>1.19</revnumber>
     <date>28 Oct 2004</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Removed distinct-nodes function </para>
     </revdescription>
    <revremark></revremark>
  </revision>

  <revision>
     <revnumber>1.20</revnumber>
     <date>11 Nov 2004</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Added doc() and document() </para>
     </revdescription>
    <revremark></revremark>
  </revision>

  <revision>
     <revnumber>1.21</revnumber>
     <date>11 Jan 2005</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Linked to XPATH2 comments </para>
     </revdescription>
    <revremark></revremark>
  </revision>

  <revision>
     <revnumber>1.22</revnumber>
     <date>14 Feb 2005</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Built under Saxon 8.3</para>
     </revdescription>
    <revremark>Note the namespace change!</revremark>
  </revision>

  <revision>
     <revnumber>1.23</revnumber>
     <date>2 Mar 2005</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Built under Saxon 8.3</para>
     </revdescription>
    <revremark>Added Date arithmetic corrections.</revremark>
  </revision>

  <revision>
     <revnumber>1.24</revnumber>
     <date>11 Apr 2005</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Built under Saxon 8.4</para>
     </revdescription>
    <revremark>Added .</revremark>
  </revision>


 <revision>
     <revnumber>1.25</revnumber>
     <date>2005-11-02T17:49:39Z</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Built under Saxon 8.5.1</para>
     </revdescription>
    <revremark>Added .</revremark>
  </revision>

 <revision>
     <revnumber>2,0</revnumber>
     <date>2005-11-04T13:07:21.0Z</date>
     <authorinitials>DaveP</authorinitials>
     <revdescription>
       <para>Built under Saxon 8.6 to CR version</para>
     </revdescription>
    <revremark>Amended to work with Saxon</revremark>
  </revision>




</revhistory>
  </d:doc>
  
  <xsl:variable name="saxonVsn">
<xsl:value-of select="system-property('xsl:product-version')"/>    
  </xsl:variable>

  <xsl:variable name="root" select="/"/>


  <xsl:strip-space elements="*"/>

  <xsl:output 
    method="html"  indent="yes" 
    include-content-type="yes" 
    />

  <xsl:output name="newFormat" method="xml" indent="yes" />



<xsl:character-map name="html">
  <xsl:output-character character="&#160;"
                        string="&amp;nbsp;" />
  <!-- tabs as four spaces -->
  <xsl:output-character character="&#x9;" string="    " />

</xsl:character-map>




 
  <xsl:template match="/">
    <html>
      <head>
        <title id="SomeId">XSLT 2.0 Test bed and exemplar</title>
      </head>
      <body bgcolor="#FFFFFF">

        <xsl:call-template name="rest"/>
        
  <p> Basic references. <a href="http://www.w3.org/TR/xquery-operators/">operators</a>, 
        <a href="http://www.w3.org/TR/xslt20">XSLT </a> the <a
href="http://www.w3.org/TR/xpath-datamodel/">data model</a>, the
<a href="http://www.w3.org/TR/xpath-functions/">XPATH 2 Functions and Operators</a> and <a
href="http://www.w3.org/TR/xpath20/">xpath 2</a>. And in case you were
wondering, the silly data types are borrowed from <a
href="http://www.w3.org/TR/xmlschema-2/#built-in-primitive-datatypes">Schema
jobbie, part 2 </a> and <a
href="http://www.w3.org/TR/xpath-datamodel/">Data model </a></p>


        <p>And if you are as confused about namespaces, see the top of
this xslt source file, or look at <a
        href="http://www.w3.org/TR/xpath20/#id-basics">2.0 Basics, in
XPath, near the end of that section. </a>. Of particular note is that
<i>xmlns:xdt="http://www.w3.org/2005/02/xpath-datatypes"</i> has
changed year. Its now 2005. Don't be caught out.</p>


      

      </body>
    </html>
  </xsl:template>

  <dp:months>
    <m>Jan</m>
    <m>Feb</m>
    <m>Mar</m>
    <m>Apr</m>
    <m>May</m>
    <m>Jun</m>
    <m>Jul</m>
    <m>Aug</m>
    <m>Sept</m>
    <m>Oct</m>
    <m>Nov</m>
    <m>Dec</m>
</dp:months>

<xsl:variable name="ver" select="concat(document('')//d:doc/revhistory/revision[last()]/revnumber,', ',document('')//d:doc/revhistory/revision[last()]/revdescription/para) "/>



  <xsl:template name="rest">
 <xsl:variable name="date" select="current-date()"/>
 <xsl:variable name="dateTime" select="current-dateTime()"/>
 <xsl:variable name="day" select="string(day-from-dateTime($dateTime))"/>
 <xsl:variable name="mon" select="document('')//dp:months/m[month-from-date($date)]"/>
 <xsl:variable name="yr" select="string(year-from-dateTime($dateTime))"/>

 <xsl:variable name='date2' select='xs:date(xs:dateTime($dateTime))'/>

 <xsl:if test="$debug > 0">
   <xsl:message>
     date: <xsl:value-of select="$date"/>
     day: <xsl:value-of select="$day"/>
     mon: <xsl:value-of select="$mon"/>
     year: <xsl:value-of select="$yr"/>

   </xsl:message>
 </xsl:if>


    <h2>Tests for xslt2 and xpath 2.</h2>
    <p style="align:right"> <i>Dave Pawson. <xsl:value-of
select="concat($day,' ',$mon,' ',$yr)"/>. Version <xsl:value-of
select="$ver"/>, at www.dpawson.co.uk</i> </p> <p>Meant to be run
against itself: saxon document.xsl document.xsl <br />Note: All the
current syntax could change. Be aware of that. Its not yet a
recommendation. But it is getting very close! </p> <p>The source XSLT
is <a href="test1.xsl">Here too </a></p>

<p>I've also <a href="xpath2.html">collated</a> a few comments on xpath2.  </p>
    <H2>Table of Contents.</H2>
    <ol>
      <xsl:for-each select="document('')//h3[@id]">
        <xsl:sort />
        <li>&#xa0; <a href="#{@id}">
        <xsl:value-of select="text()[1]"/>
</a>   </li>
      </xsl:for-each>
    </ol>
    

  
    <h3 id='buri'>base-uri()<a href="http://www.w3.org/TR/xquery-operators/#func-base-uri">w3c </a></h3>

  
    <p>You can access the base URI for a node using the base-uri() function in XPath 2.0. So if you want to know the filename for the input document, you can do:

    &lt;xsl:variable name="input-uri" select="base-uri(/)" /> which gives <br />

    <xsl:variable name="input-uri" select="base-uri(/)" /><xsl:value-of select="$input-uri"/>

and if you want to know the filename for the stylesheet, you can do:

    &lt;xsl:variable name="stylesheet-uri" select="base-uri(doc(''))" /> which gives <br/>

 <xsl:variable name="stylesheet-uri" select="base-uri(doc(''))" /><xsl:value-of select="$stylesheet-uri"/>
  </p>



 
 


 <h3 id="err">error()  <a href="http://www.w3.org/TR/xquery-operators/##func-error">w3c </a></h3>
 <p>
   Error raised, &lt;xsl:value-of select="error('Error found')"/> --
function used at end of program. The string <i>Error found</i> is
output on the error stream.. As you see I haven't used it, since it
terminates the program :-) </p>



<h3 id='proc'>system-property()  <a href="http://www.w3.org/TR/xslt20/#system-property">w3c </a></h3>

  <p><i>Note: This using Saxon,  <xsl:value-of select="system-property('xsl:vendor')"/> <br />

    Version,    <xsl:value-of select="system-property('xsl:version')"/> <br />
           Vendor,               <xsl:value-of select="system-property('xsl:vendor')"/> <br />
           Vendor-url,            <xsl:value-of select="system-property('xsl:vendor-url')"/><br />
           product-name,             <xsl:value-of select="system-property('xsl:product-name')"/><br />
  product-version,            <xsl:value-of select="system-property('xsl:product-version')"/> <br />
  Schema aware, <xsl:value-of select="system-property('xsl:is-schema-aware')"/>
  <br />
  Supports serialization, <xsl:value-of select="system-property('xsl:supports-serialization')"/>
  <br />
  Supports backwards compatibility, <xsl:value-of select="system-property('xsl:supports-backwards-compat')"/>
  <br />




supports-serialization
supports-backwards-compatibility

</i>
  </p>

<xsl:call-template name="dateTime"/>


    <xsl:apply-templates/>
  </xsl:template>


  <xsl:template name="dateTime">

 <h3 id="dtim">date and time  <a href="http://www.w3.org/TR/xquery-operators/#durations-dates-times">w3c </a></h3>
  
 <xsl:variable name="date" select="current-date()"/>
<xsl:variable name="dateTime" select="current-dateTime() "/>

<p>Declared variables are</p>
<pre>
 &lt;xsl:variable name="date" select="current-date()"/>
&lt;xsl:variable name="dateTime" select="current-dateTime() "/>
</pre>


    
<p>Obtain values using &lt;xsl:value-of select="(function)" : Functions are: </p>
<p>current-dateTime() - <xsl:value-of select="current-dateTime() "/>  </p>
<p>current-date() - <xsl:value-of select="current-date() "/>  </p>
<p>current-time() - <xsl:value-of select="current-time() "/>  </p>
<p>implicit-timezone() - <xsl:value-of select="implicit-timezone() "/> - GMT here as of Feb 05    </p>
<p>day-from-date()  <xsl:value-of select="string(day-from-date(current-date()))"/> -  which is the day of the month. </p>
<p> year-from-date()  <xsl:value-of select="string(year-from-date(current-date()))"/> </p>

<p> date from dateTime, xs:date(xs:dateTime($dateTime)) = 
<xsl:variable name='date2' select='xs:date(xs:dateTime($dateTime))'/>

Date from dateTime: <xsl:value-of select="$date2"/>
</p>


<p>month-from-date()  <xsl:value-of select="string(month-from-date(current-date()))"/>  </p>
<p>day-from-date($date) gives -  <xsl:value-of select="day-from-date($date) "/></p>




 <p>Basic date formatting: <xsl:value-of select="
 format-date($date,'[D] [Mn], [Y]')"/> from &lt;xsl:value-of select="
format-date($date,'[D] [Mn], [Y]')"/>  </p>

 
 


<p>timezone-from-dateTime($datetime) gives -  [<xsl:value-of select="timezone-from-dateTime($dateTime) "/> ]

</p>

<xsl:variable name="time" select="current-time()"/>
<p>Current time is : <xsl:value-of select="$time"/> - Using &lt;xsl:value-of select="$time"/></p>
<p>hours-from-time() gives  <xsl:value-of select="hours-from-time($time)"/> </p>
<p>minutes-from-time() gives  <xsl:value-of select="minutes-from-time($time)"/> </p>
<p>seconds-from-time() gives  <xsl:value-of select="seconds-from-time($time)"/> </p>
<p>timezone-from-time() [time zone ]gives  <xsl:value-of select="timezone-from-time($time)"/> </p>

 


 <!-- Dummy date -->
 <xsl:variable name="whenIstoppedSmoking" 
   select="xs:date('2002-09-01')"/>
 <xsl:variable name="ymd" select="current-date()" />

 <pre>Subtract dates or $xs:date() - xs:date():  
 In this case, subtract  2002-09-01Z from <xsl:value-of select="current-date()"/>

e.g.
 <xsl:variable name="dur" 
   select="$ymd - $whenIstoppedSmoking"  as="xdt:dayTimeDuration"
   />
 <xsl:sequence
 select="days-from-duration($dur)" /> days  - The duration since I stopped smoking, in days.
 <br />

Note that it is now a simple subtraction, rather than a special function.

 </pre>

 <p>Except it doesn't produce nice months/days format.. The failure
comes down to irregular months. As Mike Kay pointed out, a March date
- a Jan date will vary dependent on leap years etc. The logic goes,
convert each date to the units you want, then do the maths.</p>


 <pre>
   <xsl:variable name="nowMonths" select="month-from-date($ymd)"/>
   <xsl:variable name="nowYears" select="year-from-date($ymd)"/>
   <xsl:variable name="thenMonths" select="month-from-date($whenIstoppedSmoking)"/>
   <xsl:variable name="thenYears" select="year-from-date($whenIstoppedSmoking)"/>

   So its 
   <xsl:value-of select="if ($nowMonths &lt; $thenMonths) 
       then
        $nowYears - $thenYears -1 
       else
        $nowYears - $thenYears
         "/> years and  <xsl:value-of select="if ($nowMonths &lt; $thenMonths) then 
   ($nowMonths + 12) - $thenMonths else $nowMonths - $thenMonths"/> months


   Now using the function dp:subDates, (<xsl:value-of select="$ymd"/> - <xsl:value-of select="$whenIstoppedSmoking"/>)
   <xsl:value-of select="dp:subDates($ymd,$whenIstoppedSmoking)"/>

Boy that's messy!
See the source to find out how messy - but it can be done!
</pre>


 <!-- java call -->
 <p> External Java call to get date:  
&lt;xsl:value-of
  select="Date:toString(Date:new())" xmlns:Date="/java.util.Date" />
<xsl:value-of
  select="Date:toString(Date:new())" xmlns:Date="/java.util.Date" /> is no longer needed.
</p>


<h3 id="fmtdate">format-date[Time] and format-time. <a href="http://www.w3.org/TR/xslt20/#format-date">W3C</a></h3>

<p>Basic date and time formatting. Uses a picture string. As shown below in the more common forms.</p>

<pre>
Y  	year  	
M 	month in year 	
D 	day in month 	
d 	day in year 	
F 	day of week 	
W 	week in year 	
w 	week in month 	
H 	hour in day (24 hours) 	
h 	hour in half-day (12 hours) 	
P 	am/pm marker 	
m 	minute in hour 	
s 	second in minute 	
f 	fractional seconds

</pre>
<p>So, for example, to format the date and time a format might be</p>

<pre>
  &lt;xsl:variable name="now" select="current-dateTime()"/>
  &lt;xsl:value-of 
select="format-dateTime($now,'[Y0001][M][D01]T[H]:[m][z]','en',(),())"/>

gives


  <xsl:variable name="now" select="current-dateTime()"/>
  <xsl:value-of 
select="format-dateTime($now,'[Y0001][M01][D01]T[H]:[m][z]','en',(),())"/>

</pre>

<p>Similarly, for a time</p>

<pre>
  &lt;xsl:variable name="now" select="current-time()"/>
  &lt;xsl:value-of 
select="format-time($now,'[H]:[m] [P]','en',(),())"/>

gives


  <xsl:variable name="now" select="current-time()"/>
  <xsl:value-of 
select="format-time($now,'[H]:[m] [P]','en',(),())"/>


</pre>


<h3 id="defCollation">Default Collation. <a href="http://www.w3.org/TR/xslt20/#default-collation-attribute">W3C</a></h3>

<p>Default Collation is: <xsl:value-of select="default-collation()"/>,
obtained by <br />

&lt;xsl:value-of select="default-collation()"/>.  This seems to be 
the Unicode codepoint default. <br />

If you don't know what the collation is all about, then it's of no 
interest to you.

</p>

 <h3 id="duf">xsl:function, A User Defined Function  <a href="http://www.w3.org/TR/xslt20/#element-function">w3c </a></h3>

<pre>
&lt;xsl:function name="dp:add">
  &lt;xsl:param name="val1" />
  &lt;xsl:param name="val2" />
  &lt;xsl:sequence select="$val1 + $val2" />
&lt;/xsl:function>

(Thanks Jeni)

  Used by  &lt;xsl:value-of select="dp:add(3,4)"/>
</pre>
<p>Which gives,  <xsl:value-of select="dp:add(3,4)"/></p>

<pre>


And from the XSLT rec, a string reversal function

&lt;xsl:function name="dp:reverse">
  &lt;xsl:param name="sentence" as="xs:string"/>
  &lt;xsl:sequence
     select="if (contains($sentence, ' '))
             then concat(str:reverse(substring-after($sentence, ' ')),
                         ' ',
                         substring-before($sentence, ' '))
             else $sentence"
     as="xs:string"/>             
&lt;/xsl:function>

which is called up as:
  &lt;xsl:value-of select="dp:reverse('DOG BITES MAN')"/> 


</pre>


<p>A more constrained version of addition, using types:</p>
<pre>
&lt;xsl:function name="dp:add2">
  &lt;xsl:param name="val1" as="xs:integer" />
  &lt;xsl:param name="val2" as="xs:integer" />
  &lt;xsl:sequence select="$val1 + $val2" as="xs:integer" />
&lt;/xsl:function>
</pre>

<p>Provides, using &lt;xsl:value-of select="dp:add(1, 189)" Result is
: <xsl:value-of select="dp:add2(1, 189)" /> [Note: It should fail with
189.3 as second param.] </p>

<p>And the string reversal function gives, <xsl:value-of
select="dp:reverse('DOG BITES MAN')"/></p>


<h3 id="iof">Instance of <a
href="http://www.w3.org/TR/xpath20/#id-instance-of">W3C</a></h3>
<p>Tests if a node is of a particular data type. Testing the current
node, the stylesheet element</p>

<pre>
    Looking at &lt;xsl:value-of select="name()"/> 
         &lt;xsl:if test=".  instance of node()">
           Its an node 
         &lt;/xsl:if>
         &lt;xsl:if test=".  instance of element()">
           Its an element 
         &lt;/xsl:if>
         &lt;xsl:if test=".  instance of attribute()">
           Its an attribute
         &lt;/xsl:if>
         &lt;xsl:if test=".  instance of item()">
           Its an item
         &lt;/xsl:if>
        &lt;xsl:if test=" empty(.)">
           Its empty 
         &lt;/xsl:if>
         &lt;xsl:if test=".  instance of text()">
           Its text 
         &lt;/xsl:if>
         &lt;xsl:if test=".  instance of processing-instruction()">
           Its a pi 
         &lt;/xsl:if>
         &lt;xsl:if test=".  instance of comment()">
           Its a comment
         &lt;/xsl:if>
        &lt;xsl:if test=".  instance of document-node()">
           Its a document-node 
         &lt;/xsl:if>
       &lt;xsl:if test="$decVar  instance of xs:decimal">
           $decVar is xs:decimal 
         &lt;/xsl:if>      

.... and don't ask me what the full list of types is:
Many wonder, and few seem to know.


</pre>
<xsl:variable name="decVar" select="3.14159" as="xs:decimal"/>
<p>
    Looking at element <xsl:value-of select="name(*[1])"/> <br />
         <xsl:if test=".  instance of node()">
           Its an node <br />
         </xsl:if>
         <xsl:if test=".  instance of element()">
           Its an element <br />
         </xsl:if>
         <xsl:if test=".  instance of attribute()">
           Its an attribute <br />
         </xsl:if>
         <xsl:if test=".  instance of item()">
           Its an item <br />
         </xsl:if>
         <xsl:if test=" empty(.)">
           Its empty <br />
         </xsl:if>
         <xsl:if test=".  instance of text()">
           Its text <br />
         </xsl:if>
         <xsl:if test=".  instance of processing-instruction()">
           Its a pi <br />
         </xsl:if>
         <xsl:if test=".  instance of comment()">
           Its a comment <br />
         </xsl:if>
        <xsl:if test=".  instance of document-node()">
           Its a document-node <br />
         </xsl:if>
       <xsl:if test="$decVar  instance of xs:decimal">
           $decVar is xs:decimal <br />
         </xsl:if>

 

<pre>
&lt;xsl:value-of select=" if ($intTest instance of xs:integer) then 'True' else 'False'"/>

and with intTest defined as 
&lt;xsl:variable name="intTest" select="5" as="xs:integer"/>
</pre>
<xsl:variable name="intTest" select="5" as="xs:integer"/>
 <br /> gives a result of 
   <b><xsl:value-of select=" if ($intTest instance of xs:integer) then 'True' else 'False'"/> </b><br />

And 
   &lt;xsl:value-of select=" if ($decVar  instance of xs:integer) then 'True' else 'False'"/> - <pre>with $decVar defined as 
   &lt;xsl:variable name="decVar" 
       select="3.14159" as="xs:decimal"/> </pre>
gives
   <b><xsl:value-of select=" if ($decVar  instance of xs:integer) then 'True' else 'False'"/></b>

       </p>


<h3 id="treatas">treat as <a
href="http://www.w3.org/TR/xpath20/#id-treat-as">W3C</a></h3>

<p>Almost a temporary cast? Again Mike Kay's book offers a useful
example. A stock level element may contain either an integer count of
the items or a string indicating that the item is 'out of stock'. The
example decrements the stock, but only if it has a numeric value. A
zero or negative value indicates this out of stock count.</p>

<pre>
&lt;xsl:variable name="stock1" select="3" as="xs:integer"/>
&lt;xsl:variable name="stock2" select="'Out of Stock'" as="xs:string"/>

&lt;xsl:value-of select="
if (data($stock1) instance of xs:integer) then
     $stock1 -1
else
     -2
"/>

and

&lt;xsl:value-of select="
if (data($stock2) instance of xs:integer) then
     $stock1 -1
else
     -2
"/>


<xsl:variable name="stock1" select="3" as="xs:integer"/>
<xsl:variable name="stock2" select="'Out of Stock'" as="xs:string"/>
Testing $stock1 gives
<b><xsl:value-of select="
if (data($stock1) instance of xs:integer) then
     $stock1 -1
else
     -2
"/></b>


and testing $stock2 gives

<b><xsl:value-of select="
if (data($stock2) instance of xs:integer) then
     $stock1 -1
else
     -2
"/></b>

</pre>






       <h3 id="istar"> item()* .. sort of nodeset? <a href="http://www.w3.org/TR/xpath20/#prod-xpath-ItemType">W3C</a>
</h3>

<p>Yes, I agree it looks pretty meaningless doesn't it. However. As of
CR, its pretty essential, especially if you want to use types. And
want to generate, say, a nodeset.. sorry sequence,  in a variable.

<pre>
&lt;xsl:variable name="a" select="(//h3)[position() &lt; 3]" as="item()*"/>
</pre>

This creates a variable you can hack into using xpath quite readily.
I.e. remember item()*. 


</p>


<h3 id="types">types ... a few examples.    <a href="">W3C</a> </h3>

<p>From an explanatory email from Mike Kay, thanks Mike.<br />

Examples:

<pre>&lt;xsl:param name="x" as="item()"/></pre>

the parameter value can be any item (i.e. a node or atomic value). But
it must be a single item.

<pre>&lt;xsl:param name="x" as="item()?"/></pre>

the parameter can be a single item or an empty sequence

<pre>&lt;xsl:param name="x" as="item()+"/></pre>

the parameter must be a sequence of one or more items - an empty
sequence is not allowed

<pre>&lt;xsl:param name="x" as="item()*"/></pre>

the parameter can be any sequence of zero or more items - this places no
constraints on its value.

<pre>&lt;xsl:param name="x" as="node()*"/></pre>

the parameter can be any sequence of zero or more nodes

<pre>&lt;xsl:param name="x" as="xdt:atomicValue*"/></pre>

the parameter can be any sequence of zero or more atomic values (e.g.
integers, strings, or booleans).
</p>

<p>item()* is the most general type possible, it matches everything, like
"Object" in Java. For that reason, it can usually be omitted. But not
always, for example the default type in xsl:variable is not item()* but
document-node(), to ensure that

<pre>&lt;xsl:variable name="rtf">
  &lt;a>thing&lt;/a>
&lt;/xsl:variable>
</pre>
continues to behave like XSLT 1.0

</p>


<p>Use these to specify parameters, variable types etc.</p>



       <h3 id="cmnts">Comments in xpath expressions    <a href="http://www.w3.org/TR/xpath20/#doc-ExprComment">W3C</a></h3>

       <p> The long xpath expressions that David Carlisle and Jeni T come up with can now be commented.
       For example: <br />
       <pre>
       &lt;xsl:value-of select="//h3[@id='cmnts'] (:The h3 element with id comnts,  :)
                              /following-sibling::p[1]  (:The first p following-sibling :)
                              /xsl:value-of/@select (:the value-of child, its select attribute :)
                             "/>  
     </pre>

     This expression gives -

  <xsl:value-of select="//h3[@id='cmnts'] (:The h3 element with id comnts,  :)
                              /following-sibling::p[1]  (:The p element child (:Oh yes it is:):)
                              /xsl:value-of/@select (:the value-of child, its select attribute :)
     "/>  which as you can see, includes the comments! Note they can be nested too! 

</p>

       <h3 id="castable">Castable and cast       <a href="http://www.w3.org/TR/xpath20/#id-castable">W3C </a> </h3>

       <p>Tests whether a given value is castable into a given target type. Returns boolean.</p>

       <p>
<xsl:variable name="decVar" select="3.14159" as="xs:decimal"/>
<xsl:variable name="intVar" select="3" as="xs:integer"/>
         <pre>
&lt;xsl:variable name="decVar" select="3.14159" as="xs:decimal"/>
&lt;xsl:variable name="intVar" select="3" as="xs:integer"/>
         &lt;xsl:if test="$intVar castable as xs:decimal">
           Yes, we can convert an int to a decimal
         &lt;/xsl:if>
         &lt;xsl:if test="$decVar castable as xs:float">
           and we can change decimals to floats.
         &lt;/xsl:if>
 Then do it, using 
&lt;xsl:value-of select="$decVar cast as xs:float"/>
</pre>
    <xsl:if test="$intVar castable as xs:decimal">
           Yes, we can convert an int to a decimal
         </xsl:if>
         <xsl:if test="$decVar castable as xs:float">
           and we can change decimals to floats.
         </xsl:if>
 Then do it, using 
         <b>    <xsl:value-of select="$decVar cast as xs:float"/> </b> <br />
See the source to see this working.

</p>


 <h3 id="gnufp">get-namespace-uri-for-prefix function <a href="http://www.w3.org/TR/xquery-operators/#func-get-namespace-uri-for-prefix">w3c </a></h3>
 <pre>&lt;xsl:value-of select="namespace-uri-for-prefix('dp',document('')//dp:analyze-string)"/> </pre>


 <p> This provides
the reverse mapping from prefix (dp in this case) to a full namespace and 

gives - 
 <b>
<xsl:value-of 
select="namespace-uri-for-prefix('dp',document('')//dp:analyze-string)"
  /></b>

 
</p>
 <h3 id='sfns'>string-join()   string functions:  <a href="http://www.w3.org/TR/xquery-operators/#func-string-join">w3c </a></h3>
<pre>
  &lt;xsl:value-of select="string-join(('Now', 'is', 'the', 'time', ' '), ")/> 
</pre>
<p>  The output is: 

<b><xsl:value-of select="string-join(('Now', 'is', 'the', 'time'),' ')"/></b></p>

<p>Note the difference between this and </p>
<pre>&lt;xsl:value-of select="concat('Now', 'is', 'the', 'time')" /></pre>

<p>Which gives:<b>
<xsl:value-of select="concat('Now', 'is', 'the', 'time')" />
</b>
</p>

<p>Michael Kay put a clever example on the list: The requirement was
to reverse a string. This 

<pre>
&lt;xsl:variable name="in" select="'Now is the time'"/>
  &lt;xsl:value-of select=" string-join(
                        for $i in string-length($in) to 1 return substring($in, $i, 1),'')"/>

</pre>
This gives: <br />

<xsl:variable name="in" select="'Now is the time'"/>
<b>
<xsl:value-of select="string-join(
for  $i in (reverse((1 to string-length($in))))
return (substring($in, $i, 1)),'')"/></b> 

</p>

<h3 id="reverse">reverse() function <a href="http://www.w3.org/TR/xquery-operators/#func-reverse">W3C</a></h3>

<p>A function to reverse a sequence. Needed since the WG have removed
the option to use 'for n to n-x', Hence, taking a sequence one to N,
which we really want to process by decrement: </p> 

<pre>
&lt;xsl:variable name="in" select="'Now is the time'"/>
&lt;xsl:sequence select="reverse((1 to string-length($in)))"/>

 produces...
</pre>

<xsl:variable name="in" select="'Now is the time'"/>
<xsl:sequence select="reverse((1 to string-length($in)))"/>


 <h3 id="ewith">ends-with() function<a href="http://www.w3.org/TR/xquery-operators/#func-ends-with">w3c </a></h3>
 
<p>A boolean returning true if param 1 ends with param 2. Both
parameters are strings. Complements the existing 'starts-with'
functionality.</p>

 <pre>&lt;xsl:value-of select='ends-with("goldenrod","rod")'/> </pre>
 <p> returns "<xsl:value-of select="ends-with('goldenrod','rod')"/>"

</p>

 <h3 id="ucfn">upper-case()<a href="http://www.w3.org/TR/xquery-operators/#func-upper-case">w3c </a></h3>

 <p>Case changing:</p>

 <pre> &lt;xsl:value-of 
select="upper-case('The quick Brown fox Jumps over the lazy dog' 
</pre>
<p>Gives:
"<xsl:value-of select="upper-case('The quick Brown fox Jumps over the lazy dog') "/> "    
</p>

 
<h3 id="lcfn">lower-case()<a href="http://www.w3.org/TR/xquery-operators/#func-lower-case">w3c </a></h3>


 <p>Case changing:</p>

 <pre> &lt;xsl:value-of 
select="lower-case('The Quick Brown Fox Jumps Over The Lazy Dog' 
</pre>
<p>Gives:
"<xsl:value-of select="lower-case('The quick Brown fox Jumps over the lazy dog') "/> "    
</p>

 



 <h3 id="match">matches() regular expression in xslt <a
href="http://www.w3.org/TR/xquery-operators/#func-matches">w3c
</a></h3>
<p>Matches on the entire input, returns true or false.</p>


<p>Testing the matches function, with a string variable having value  'abd124' and using the regexp "[a..d|0..9]*" Hence 
</p>

<pre> &lt;xsl:value-of select="matches ($inputString,'[a..d|0..9]*')"/>
</pre>
<p><xsl:variable name="inputString" select="'abd124'"/>
Returns <xsl:value-of select="matches ($inputString,'[a..d|0..9]*')"/>
</p>

<xsl:variable name="str" select="'the quick brown fox jumps over the lazy dog'"/>


 <h3 id="repl">replace()  - Text replace function  <a href="http://www.w3.org/TR/xquery-operators/#func-replace">w3c </a></h3>
<p>replace() function. E.g. turn spaces into *** in "the quick brown
fox jumps over the lazy dog"<br /> Uses:
</p>
<pre> &lt;xsl:value-of select="replace($str, ' ', '***')" /> </pre>
<p>Gives - <b>
<xsl:value-of select="replace($str, ' ', '***')" />
</b>
 <br />[So any occurrences of param2 in param1 are replaced with param3] </p>

 <h3 id="tok">tokenize()  <a href="http://www.w3.org/TR/xquery-operators/#func-tokenize">w3c </a></h3>


 <p>Tokenise!!! (One of my favourites). Do a for-each over the output
 of tokenize("The cat sat on the mat", "\s+") to process each item as
 if it were a child of the input element. Enables easy processing of
 regularly split text content </p>

 <pre>
  &lt;xsl:for-each select='tokenize("The cat sat on the mat", "\s+")'>
&lt;token>
      &lt;xsl:value-of select="."/>
&lt;/token>
  &lt;/xsl:for-each>
</pre>

<p>  <xsl:for-each select='tokenize("The cat sat 
on the mat", "\s+")'>
  &lt;token><xsl:value-of select="."/>&lt;/token><br />
    </xsl:for-each> Note that </p>

    <pre>
&lt;quote>If a separator occurs at the start of the $input string, 
      the result sequence will start with a zero-length string. 
&lt;/quote>, 
    </pre>
    <p>and that the \s+ caters for a tab, space and newline character in the input string.
</p>


 <h3 id="norm">normalize-space()  Normalise text  <a href="http://www.w3.org/TR/xquery-operators/#func-normalize-space">w3c </a></h3>
<p>Normalisation: Input as</p>

<pre>[The
quick
brown ....
fox

]</pre>

<p>Function used </p>
<pre>
&lt;xsl:value-of select="normalize-space('The
quick
brown     
fox

')"/>
 </pre>

<p>Result: [<xsl:value-of select="normalize-space('The
quick
brown     
fox

')"/>]</p>


 <h3 id="scmp">compare() - String Comparison  <a href="http://www.w3.org/TR/xquery-operators/#func-compare">w3c </a></h3>
 <p>String comparison; With and without a character entity. </p>
<xsl:variable name="stSt" select="'The quick brown fox ....'"/>
<xsl:variable name="entStr" select="'Th&#101; quick brown fox ....'"/>

<pre>
Definitions:
&lt;xsl:variable name="stSt" select="'The quick brown fox ....'"/>
&lt;xsl:variable name="entStr" select="'Th&amp;#101; quick brown fox ....'"/>

&lt;xsl:value-of select="compare($stSt, $entStr)"/>

</pre>
<p>
  Result is : <xsl:value-of select="compare($stSt, $entStr)"/> </p>
<pre>  Interpret the results as below.
-1  => less than 
 0  => Equal 
+1  => Greater than
</pre>
<p>Which indicates equality when the XSLT processor makes the comparison.</p>

 <h3 id="uri">resolve-uri() - Uri resolution  <a href="http://www.w3.org/TR/xquery-operators/#func-resolve-uri">w3c </a></h3>
 <p>URI rsolution - absolute, or against a base URI. </p>
 <pre>
 &lt;xsl:value-of select="resolve-uri('./test1.xsl')"/>
(Which is this file)
 </pre>

 <p> Gives: <xsl:value-of select="resolve-uri('./test1.xsl')"/> 
 Indicating the full path name of the file, in this case. The parameter is meant to be a relative uri.
</p>
<p>The second form takes an absolute location as a second parameter, such as might be used for a server root.
</p>
<pre>
  &lt;xsl:value-of select="resolve-uri('test1.xsl','file://c:/')"/>
</pre>
<p>This gives <b>
<xsl:value-of select="resolve-uri('test1.xsl','file://c:/sgml/')"/> </b> which resolves the relative URI against the base.
</p>

<p>I'm told that <a href="http://java.sun.com/j2se/1.4.1/docs/api/java/net/URL.html#URL(java.net.URL,%20java.lang.String)">the Java docs</a> explains it. Baffles me.</p>







 <h3 id="resolveqname">resolve-QName() - Builds a qname from the in-scope namespaces.  <a
href="">w3c
</a></h3>

<p>E.g, using the dp:months element,  create a QName dp:newdoc, 
<pre>
&lt;xsl:value-of select="resolve-QName('dp:newdoc',//dp:months)"/> gives <xsl:value-of select="resolve-QName('dp:newdoc',//dp:months)"/>
Then check if it is a qname... using
&lt;xsl:if test="resolve-QName('dp:newdoc',//dp:months) instance of xs:QName">
Its a QName!! 
&lt;/xsl:if>
<xsl:if test="resolve-QName('dp:newdoc',//dp:months) instance of xs:QName">
Its a QName!! 
</xsl:if>
</pre>
</p>

 <h3 id="ndb">root() - find root node of context.  <a
href="http://www.w3.org/TR/xquery-operators/#func-xpath-name">w3c
</a></h3>

 <p>Used to find the root node of the current document, with respect to the  current-node(),</p>

 <p>
 <pre>
 &lt;xsl:value-of select="name(root(.)/*[1]) </pre>
 gives: <b><xsl:value-of select="name(root(.)/*[1])"/></b> <br />

 


Note: Presumes root() returns the document node, which is why the
first child is used as shown above.  Possibly removes the necessity of
saving the root node when you are mid xsl:for-each, and wish to access
the current document.  </p>


 <h3 id="seq">index-of() - Find the index of one item in a sequence <a
href="http://www.w3.org/TR/xquery-operators/#func-index-of">w3c
</a></h3>

 <p>Sequence based.  Remember that we've lost the node-list idea, life's full of sequences now. 

Load  variable with a number of items. E.g. </p>
 <p>
 <pre>&lt;xsl:variable name="seq" select="$root//h3"/> </pre>

pick the 5th item. 

 <pre>
&lt;xsl:variable name="oneChild" select="$seq[5]"/> 
Test it using
&lt;xsl:value-of select="index-of($seq,$oneChild)" /> 
</pre>
</p>

<p>
<xsl:variable name="seq" select="$root//h3"/>
<xsl:variable name="oneChild" select="$seq[5]"/>
The result  is 
<xsl:value-of select="index-of($seq,$oneChild)" /> <br />

or, using a simple text example, 
 </p>

 <pre>
&lt;xsl:value-of select="index-of(('a','b','c','d','e','f' ),'c')"/> 

gives a result of  <xsl:value-of select="index-of(('a','b','c','d','e','f' ),'c')"/>
   </pre>


 <h3 id="mt">empty() - The empty function <a href="http://www.w3.org/TR/xquery-operators/#func-empty">w3c </a></h3>
<p>Empty tests:
Input document reads
<pre>
&lt;dp:mttests>
&lt;dp:t1/>
&lt;dp:t2>&lt;el/> &lt;/dp:t2>
&lt;dp:t3>xxx &lt;/dp:t3>
&lt;/dp:mttests>


Tested with
t1 shows as: &lt;xsl:value-of select="empty($root//dp:mttests/t1/*)"/>
t2 shows as: &lt;xsl:value-of select="empty($root//dp:mttests/t2/*)"/>
t3 shows as: &lt;xsl:value-of select="empty($root//dp:mttests/t3/*)"/> 


</pre>
Each is tested using the empty() function. <br />
t1 shows as: <xsl:value-of select="empty($root//dp:mttests/t1/*)"/> <br />
t2 shows as: <xsl:value-of select="empty($root//dp:mttests/t2/*)"/> <br />
t3 shows as: <xsl:value-of select="empty($root//dp:mttests/t3/*)"/> <br />

Note that empty here seems to be defined as containing no elements,
i.e. text content is ignored.

</p>
<h3 id="exist">exists() function  <a href="http://www.w3.org/TR/xquery-operators/#func-exists">w3c </a></h3>

  <pre>Using
&lt;xsl:if test="exists($root//dp:mttests/t1)">
  mttests/t1 is a non-empty sequence
&lt;/xsl:if>

&lt;xsl:if test="exists($root//dp:mttests/t2)">
  mttests/t2 is a non-empty sequence
&lt;/xsl:if>
  &lt;xsl:if test="not(exists($root//dp:mttests/t3/el)">
  mttests/t3 is an empty sequence
&lt;/xsl:if>

</pre>

<p> Gives: <br />
<xsl:if test="exists($root//dp:mttests/t1)">
  dp:mttests/t1 is a non-empty sequence<br />
</xsl:if>

<xsl:if test="exists($root//dp:mttests/t2/*)">
  dp:mttests/t2 is a non-empty sequence<br />
</xsl:if>

<xsl:if test="not(exists($root//dp:mttests/t3/el))">
  dp:mttests/t3 is an empty sequence<br />
</xsl:if>
<br /> Note the inversion on the last test.

</p>

<h3 id="dist">distinct-values() function <a
href="http://www.w3.org/TR/xquery-operators/#func-distinct-values">w3c
</a></h3>

<p>We can now test for distinct nodes and values. Note the difference! <br />

<xsl:variable name="ns1" as="xs:integer*">
  <xsl:sequence select="(1,2,3,4,5,3)"/>
</xsl:variable>


1. Define a variable with one duplicate item - the 3.  

<pre>&lt;xsl:variable name="ns1" select="(1,2,3,4,5,3)"/> </pre>
2. Count its contents 
<pre>&lt;xsl:value-of select="count($ns1)"/>  </pre>
Gives <xsl:value-of select="count($ns1)"/>  <br />

3. Remove duplicates and count the resulting nodes, 
<pre>&lt;xsl:value-of select="count(distinct-values($ns1))"/></pre>
gives: <xsl:value-of select="count(distinct-values($ns1))"/>   <br />


</p>
<p>Then picking out the two distinct values with 

<pre>
&lt;xsl:for-each select="distinct-values(//dp:distinct/dp:val1)"> 
</pre>
 gives: 
<b><xsl:for-each select="distinct-values(//dp:distinct/dp:val1)">
  <xsl:value-of select="."/> <br />
</xsl:for-each>
</b>

 </p>




 <h3 id="cpy">copy-of() - Copying - omitting namespaces  <a href="http://www.w3.org/TR/xslt20/#shallow-copy">w3c </a></h3>

<p>New attribute to the copy function. Copy without copying
namespace. Adds the attribute copy-namespaces="no". <br /> View source
should show a &lt;para> element without namespaces, then the same with
a normal copy-of <br />

[<xsl:copy-of select="document('')//d:doc/revhistory/purpose/para"
  copy-namespaces = "no" />] (no ns) <br />
[<xsl:copy-of select="document('')//d:doc/revhistory/purpose/para"
   />] (has ns)
</p>
<p>The two forms are:</p>

<pre>
1. &lt;xsl:copy-of select="document('')//d:doc/revhistory/purpose/para"
  copy-namespaces = "no"/>
2. &lt;<xsl:copy-of select="document('')//d:doc/revhistory/purpose/para" />

</pre>

<p>
the output is shown below. Here's one I prepared earlier, I think is the phrase.
</p>
<pre>
 &lt;para>Test Harness for XSLT and xpath 2 constructs&lt;/para>
and 
  &lt;para xmlns:d="rnib.org.uk/tbs#" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:fn="http://www.w3.org/2002/11/xquery-functions" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema-datatypes" 
  xmlns:op="http://www.w3.org/2002/11/xquery-operators" 
  xmlns:dp="http://www.dpawson.co.uk/namespace" 
  xmlns:pref="http://www.dpawson.co.uk" 
  xmlns:saxon="http://saxon.sf.net/">Test Harness for XSLT and xpath 2 constructs&lt;/para>] (has ns)
</pre>

<p>Now you can see why this functionality is helpful.</p>

<h3 id="ndname">node-name() <a
href="http://www.w3.org/TR/xquery-operators/#func-node-name">w3c </a></h3>
<p>Obtain the qualified name for a node. E.g.</p>

<pre>
[&lt;xsl:value-of select="node-name(//xsl:template[1])"/>]
whose namespace is &lt;xsl:value-of select="namespace-uri(//xsl:template[1])"/>

[<xsl:value-of select="node-name(//xsl:template[1])"/>]
whose namespace is <xsl:value-of select="namespace-uri(//xsl:template[1])"/>
</pre>

<h3 id="nsuri">namespace-uri() <a
href="http://www.w3.org/TR/xquery-operators/#func-namespace-uri">w3c </a></h3>
<p>Returns the namespace URI of the node passed as a parameter, or the current node. Example immediately above.</p>

<h3 id="cpysep">xsl:sequence - a literal sequence <a
href="http://www.w3.org/TR/xslt20/#element-sequence">w3c </a></h3>


<p>Creates one of these new  sequences! 
<pre> E.g.
&lt;xsl:sequence select="(1,2,3,4)" />
</pre>

This shows it using a simple sequence of numbers. <br />
the result is <b><xsl:sequence select="(1,2,3,4)" /> </b> <br />

Note that 
<pre>&lt;xsl:value-of select="(1,2,3,4)" separator=", "/> 
</pre>
works just the same, but with the separator, 
<br />
to give 

  <xsl:value-of select="(1,2,3,4)" separator=", "/>

</p>
<p>Another oddity is the need to use double brackets (( when
specifying a sequence, as in</p>

<pre>
1. &lt;xsl:value-of select="min((1,2,3,4))"/>
2. &lt;xsl:value-of select="min(1,2,3,4)"/>
</pre>

<p>If the second form is used an error is reported. See <a href="#expr">this</a> for an explanation.</p>


<p>Another use of this is to create a sequence containing duplicates.

<pre>&lt;xsl:sequence select="(//h3, //h3[5])"/>
</pre>
Should you ever need it.
</p>


<h3 id="lsConstructor">() as a list constructor? <a href="http://www.w3.org/TR/xpath20/#id-sequencetype">W3C - I think, but I could be wrong. Its well hidden </a>  </h3>

<p>Another rather subtle use of sequences. The min() function takes a
single argument, which is a sequence. So to find the minumum of two
values X and Y, write

<pre>min((X, Y))</pre>

Note the double parentheses: the outer ones say that this is a list of
arguments, the inner ones say that (X, Y) is a sequence containing X and
Y.</p>


<p>It's not technically a constructor,

the "," is a list concatenation operator: A,B is the concatenation of
two lists.
<a name="expr"/>
The inner parens in min((A, B)) are needed because a function argument
must be an <i>ExprSingle</i> rather than an <i>Expr</i>. An ExprSingle
is effectively an expression that does not contain a top-level
comma. A top-level comma is not allowed here for obvious reasons - it
would be taken as the separator between arguments in the function
call.

</p>

<p>Note that string-length() first parameter needs to be a single expression, ExprSingle!</p>

 <h3 id="sort1">xsl:sort - Sorting.  <a href="http://www.w3.org/TR/xslt20/#element-sort">w3c </a></h3>

 <p>An additional attribute, case-order, can take values of  upper-first  or  lower-first, which helps with sorting. </p>

<xsl:variable name="rString"
  select="('AB','aA','c', 'dEF', 'ghij','GHj' ,'KLmno','PqrSt','uvwxy','z','123', '456789')"/>


<p>Sorting: descending order, upper case first.
<br />
  <pre>Given: 
&lt;xsl:variable name="rString"
  select="('AB','aA','c', 'dEF', 'ghij','GHj' ,'KLmno','PqrSt','uvwxy','z',
  '123', '456789')"/>

and 

&lt;xsl:for-each select="$rString">
&lt;xsl:sort select="."  case-order ="upper-first" order="descending"    />
  &lt;xsl:value-of select="." /> &lt;xsl:text> &lt;/xsl:text>
&lt;/xsl:for-each>
</pre>

gives: 

<b>
<xsl:for-each select="$rString">
<xsl:sort select="."  case-order ="upper-first" order="descending"    />
  <xsl:value-of select="." /> <xsl:text> </xsl:text>
</xsl:for-each>
</b>
</p>
<p>Note in the above that the sort order has placed upper case first
and changed the order to descending. A very useful addition.</p>




 <h3 id="sskey">xsl:perform-sort -  Sorting function <a href="http://www.w3.org/TR/xslt20/#element-perform-sort">w3c </a></h3>
<p>Trying to figure out the difference between xsl:perform-sort and xsl:sort. It seems to wrap xsl:sort, so I've no idea of its functionality.


</p>
<p>Mike Kay tells me: quote. xsl:sort specifies how for-each and
apply-templates should do their work.  xsl:perform-sort is an
instruction that does sorting and nothing else; it's useful for
example if you want to sort a sequence of elements before doing a
grouping operation. It's really just a shorthand for
<pre>
&lt;xsl:for-each select="xxx">
  &lt;xsl:sort select="yyy"/>
  &lt;xsl:sequence select="."/>
&lt;/xsl:for-each>
</pre>
</p>


 <h3 id="anStr">xsl:analyze-string  - Analyse string, using regular expressions.  <a href="http://www.w3.org/TR/xslt20/#element-analyze-string">w3c </a></h3>
 
 <p>analyze-string function. With a string, whose original content was "
 <pre>   
<b> <xsl:value-of select="document('')//dp:analyze-string"/></b>
</pre>

I Want to change the word <b>need</b> into &lt;par>. This is done using
 </p>
     <pre>
 &lt;xsl:value-of select="document('')//dp:analyze-string"/>." Change need into &lt;par>
 &lt;xsl:analyze-string select="document('')//dp:analyze-string" 
   regex="need">

   &lt;xsl:non-matching-substring>&lt;xsl:text/>
   (&lt;xsl:value-of select="."/>)&lt;xsl:text/>
   &lt;/xsl:non-matching-substring>

   &lt;xsl:matching-substring>
     &lt;span style="color:blue">&lt;xsl:text>&lt;par> &lt;/xsl:text> &lt;/span>
   &lt;/xsl:matching-substring>
 &lt;/xsl:analyze-string>
</pre>

<p> Result is : <br />
 <xsl:analyze-string select="document('')//dp:analyze-string" 
   regex="need">
   <xsl:non-matching-substring><xsl:text/>
   (<xsl:value-of select="."/>)<xsl:text/>
   </xsl:non-matching-substring>
   <xsl:matching-substring>
     <span style="color:blue"><xsl:text>&lt;par> </xsl:text> </span>
   </xsl:matching-substring>
 </xsl:analyze-string>
     </p>
     <p>Note the two child elements, matching and non-matching. I've
added brackets round the 'non-matching' parts of the input, so you can
see the output.</p>

     <p>With a more complex String, the regex-group(n) can be used to
pick out individual sub-groups.</p>

     <p>Jeni Tennison gave a slightly more educational example on the list which I changed to show all the matches. It brings out a few points.</p>
     <pre>

&lt;xsl:variable name="regex" select="'(([^_]*)_PARA)'"/>
  &lt;xsl:variable name="input" select="'ABC_PARA__PARA'"/>

    &lt;xsl:variable name="res" as="item()*">
   &lt;xsl:analyze-string select="$input" regex="{$regex}">
      &lt;xsl:matching-substring>
        &lt;xsl:for-each select="for $i in (1 to 10)  return $i">
          &lt;xsl:if test="not(string-length(regex-group(.)) = 0)">
            &lt;match>&lt;xsl:value-of select="regex-group(.)"/>   &lt;/match>
          &lt;/xsl:if>
        &lt;/xsl:for-each>
      &lt;/xsl:matching-substring>
      &lt;xsl:non-matching-substring>
        &lt;mismatch>&lt;xsl:value-of select="."/>&lt;/mismatch>
      &lt;/xsl:non-matching-substring>
    &lt;/xsl:analyze-string>
  &lt;/xsl:variable>

  &lt;xsl:copy-of select="$res"/>

The output is:

&lt;match>ABC_PARA&lt;/match>
&lt;match>ABC&lt;/match>
&lt;mismatch>_&lt;/mismatch>
&lt;match>_PARA&lt;/match>

</pre>


<p>From this, its possible to see just what is filtered within each
group. </p> <p>There are a total of 3 matches, sequenced as two
matches, a mismatch and the last match. Note the sequence? It is
ordered, and will be different if you write it directly to the
output. Note also that the regex attribute is an Attribute Value
Template. I presume less than 11 matches, and test each for a zero
string length of the regexp-group() function. This provides a simple
structure which can then be accessed programmatically to obtain the
nth match, or the nth mismatch, should that be what you want. </p>


 <h3 id="else">if then else - conditional value-of? <a href="http://www.w3.org/TR/xpath20/#id-conditionals">w3c </a></h3>
 <p>With a defined function</p>
 <pre>
&lt;xsl:function name="dp:reverse">
  &lt;xsl:param name="sentence" as="xs:string"/>
  &lt;xsl:sequence
   select="<b>if</b> (contains($sentence, ' '))
           <b>then</b> concat(dp:reverse(substring-after($sentence, ' ')),
                         ' ',
                         substring-before($sentence, ' '))
           <b>else</b> $sentence"
     as="xs:string"/>             
&lt;/xsl:function>
</pre>

     <p>An If then else conditional, within an attribute.<br />
     Called by   <pre>&lt;xsl:value-of select="dp:reverse('DOG BITES MAN')"/></pre>
     which (from the rec) reverses the words in a sentence. <br />
     Result is <b><xsl:value-of select="dp:reverse('DOG BITES MAN')"/></b>

</p>



 <h3 id="wdtype">Wrong data types.  <a href="http://www.w3.org/TR/xslt20/#dt-dynamic-error">w3c </a></h3>

<p>Getting it wrong, Wrong data type that is. (who needs
that!). Firstly the correct use. Again from the rec, a function,
<pre>&lt;xsl:value-of select="dp:roman(34)"/></pre> which should turn the 34 into
XXXIV. <br />

The result is <b><xsl:value-of select="dp:roman(34)"/> </b> - works fine. <br />
Now lets pass it a string such as: <pre>&lt;xsl:value-of select="dp:roman('34')"/></pre>

Result is .... well it would be, the stylesheet crashes, or more exactly, the program terminates.
Saxon <xsl:value-of select="$saxonVsn"/> gives an error of
<pre>
Required type is xs:integer; supplied value has type xs:string
Transformation failed: Failed to compile stylesheet. 1 error detected.
</pre>

</p>

<!--

 <h3 id="typAnot">xsl:type   - Type annotation  <a href="http://www.w3.org/TR/xslt20/#d0e11091">w3c </a></h3>

<p>Types. below is an element, with a type annotation. Note that no
attribute is output in the serialised form. The line reads <br />

&lt;fred>34&lt;/fred>, <br />

Note: You need a schema aware processor to hack this properly. I
haven't found a use for W3C schema yet. Hence it is commented out.

</p>

-->
<!-- Category: instruction -->
 <h3 id="ans">xsl:namespace - Adding a namespace with xsl:namespace  <a href="http://www.w3.org/TR/xslt20/#element-namespace">w3c </a></h3>
<p>The instruction
<pre>  
&lt;xx:head>
&lt;xsl:namespace name='xx'>http://www.dpawson.co.uk/namespace#&lt;/xsl:namespace>
&lt;/xx:head>
</pre>

adds a namespace definition to the nearest ancestor element, so in the
example, the head element would be in the xx namespace.  I don't think
stylesheet authors are that lazy? Do you?

</p>



<h3 id="quot">quotes - Changes in the use of quotes  <a href="http://www.w3.org/TR/xpath20/#prod-StringLiteral">W3C </a>   </h3>

<p>
  <xsl:variable name="qStr" select='"Some ""Content""  with quotes"'/>


  Given a string such as 
  <pre>
&lt;xsl:variable name="qStr" select='"Some ""Content""  with quotes"'/>
                                           ^^       ^^
(Note the quote doubling)
  </pre>
 using the translate function, 

  <pre>
&lt;xsl:value-of select="translate($qStr, '&quot;', '''  ')"/>
  </pre>
which is a (single => double) gives <br />
  <b><xsl:value-of select="translate($qStr, '&quot;', '''')"/> </b> <br />

The rule becomes: Use one kind of quotes for XML attributes, the
other kind for XPath string literals. Use XML escaping for the XML
attribute quotes. Use XPath escaping (i.e. doubling) for the XPath
quotes.
</p>

<h3 id="resDoc"> xsl:result-document. Creating multiple output documents. Direct use <a href="http://www.w3.org/TR/xslt20/#element-result-document">W3C</a>  </h3>

<p>Formalising the various processor extensions, this provides the way
to generate more than one output document. </p>

<p>No idea what the schema related ... attributes are all about. The basics are shown below.</p>
<pre>
&lt;xsl:result-document
  format = qname
  href = { uri-reference }>
  &lt;!-- Content: sequence-constructor -->
&lt;/xsl:result-document>
</pre>

<p>The example here writes to res-doc.html all the titles from this
document and links them back into this document. Just to see what
happens, I've added an additional instruction into the output. After
writing the &lt;head> element, I've added the

<pre>
&lt;xsl:namespace name='xx'>http://www.dpawson.co.uk/namespace#&lt;/xsl:namespace>
</pre>

instruction. If you look at the output file (res-doc.html), you'll see
this adds the namespace declaration into the element!

The code is:</p>


<pre>
&lt;xsl:result-document
href="res-doc.html"
 >

  &lt;html>

    &lt;head>
  <b>&lt;xsl:namespace name='xx'>http://www.dpawson.co.uk/namespace#&lt;/xsl:namespace></b>
      &lt;title>Test output.&lt;/title>
    &lt;/head>
    &lt;body>
      &lt;ul>
  &lt;xsl:for-each select="$root//h3">
    &lt;li> &lt;a href="exampler.html#{@id}">   &lt;xsl:value-of select="."/>&lt;/a>&lt;/li>
  &lt;/xsl:for-each>
&lt;/ul>
&lt;/body>
&lt;/html>
&lt;/xsl:result-document>
</pre>

<xsl:result-document
href="res-doc.html"
validation="strip"

  >
  <html>
    <head>
 <xsl:namespace name='xx'>http://www.dpawson.co.uk/namespace#</xsl:namespace>
      <title>Test output.</title>
    </head>
    <body>
      <ul>
  <xsl:for-each select="$root//h3">
    <li> <a href="exampler.html#{@id}">   <xsl:value-of select="."/></a></li>
  </xsl:for-each>
</ul>
</body>
</html>
</xsl:result-document>

<p>See also <a href="#rdoc">an indirect use of this  </a> </p>

<h3 id="dtim2">current-time() - Second check on time function.   <a href="http://www.w3.org/TR/xpath20/#eval_context">W3C </a>   </h3>
<p>Just checking. The time now is <xsl:value-of select="current-time()"/> according to &lt;xsl:value-of select="current-time()"/>. This should be the same time as shown at -<a href="#dtim">here</a>, since xpath says 
<i>If invoked multiple times during the execution of a query or transformation, these functions always returns a consistent result</i>



</p>

<h3 id="gloss">terminology.   <a href="http://lists.w3.org/Archives/Member/w3c-archive/2003Apr/att-0111/Overview-diff.html#glossary">W3C </a>   </h3>

<p>See the W3C definitions.</p>





<h3 id="escU">escape-html-uri() - Escaping Special characters in a URI   <a href="http://www.w3.org/TR/xquery-operators/#func-escape-html-uri">W3C </a>   </h3>

<p>Addresses the need to replace 'special' characters in such as a
URL. Escapes a URI in the manner html user agents handle attribute
values that expect URIs. </p>


<p>Given a string such as <pre>

http://www.example.com/~bÃ©bÃ©


Using 
&lt;xsl:value-of 
select='escape-html-uri("http://www.example.com/~bÃ©bÃ©",true())'/> 


gives </pre>

 <xsl:value-of select='escape-html-uri("http://www.example.com/~bÃ©bÃ©")'/> <br />
 

</p>



<h3 id="grp">xsl:for-each-group  - A New grouping method    <a href="http://www.w3.org/TR/xslt20/#d5e12772">W3C </a>   </h3>

<p>Since this requires input, I've created a separate file for
this. See <a href="testg.xsl">this separate xslt file </a> and <a
href="testg.xml">this xml file </a>. Certainly answers most of the
needs of xslt users. Run the stylesheet against the xml source file
and have a look at the output.</p>



<h3 id="uq">every , The Universal quantifier   <a href="http://www.w3.org/TR/xpath20/#id-quantified-expressions">W3C </a>   </h3>

<p>This  uses the predicate <pre>'every $x in ....' </pre>to check that each h3 element has an id value which is not empty. The syntax is:</p>
<pre>
 &lt;xsl:if 
  test="not(every $id in (//h3) satisfies (not(empty($id/@id)) and $id/@id  )) "
</pre>

<p> Of course, to show it up, there is one without the requisite id value. <br />
<xsl:if test="not(every $id in (//h3) satisfies (not(empty($id/@id)) and $id/@id  )) ">
  <br /><b style='color:red'>Warning,  h3 element found with id attribute missing/empty</b>
   <xsl:for-each select=" //h3[@id = ''] | //h3[not(@id)]">
     Content is: <xsl:value-of select="."/>
   </xsl:for-each>
 </xsl:if>
 <br />
  

</p>

<h3> This heading is included to produce an error.</h3>

<h3 id="vc">Value Comparisons...  eq, ne, is, isnot etc <a href="http://www.w3.org/TR/xpath20/#id-value-comparisons">W3C</a></h3>
<p>Those nice simple days of = and != are over. The list now is quite long. 
The list is:

<pre>
eq  equality
ne  not equal
lt  less than
le  less than or equal
gt  greater than
ge grater than or equal
</pre>


Notable points are:</p>

<ul>
  <li>Value comparisons are intended for comparing single values. So don't use them for comparing a string with a node-set (sequence) and expect it to work.</li>
  <li>Unless you (or at least your stylesheets) are type aware, comparisons are done as strings.</li>
</ul>

<p>Examples?</p>

<pre>
  &lt;xsl:if test="p eq ../'The cat sat on the mat'"> 
</pre>

<p>Normal string equality... except that if there is more than one p element, its an error. Now you see what they mean about comparing single values. </p>


<p>Node comparisons occur in the same way, except they apparently need a separate verb, 
<pre>&lt;xsl:if test="a is b"></pre>
<tt>is</tt> and <tt>isnot</tt> are the two verbs in question. The two nodes must be the same for <tt>is</tt> to return true, different for <tt>isnot</tt> to return true. The rec gives an example of the same node
accessed via two different means, e.g.

<pre>
  &lt;xsl:if test=" //*[@id = 'nodeA'] is title[1]">
     
</pre> Returns true if the only node with the id attribute equal to
string value <tt>nodeA</tt> is also first child named <tt>title</tt>.  </p>


<h3 id="some">some , The Universal quantifier.<a href="http://www.w3.org/TR/xpath20/#id-quantified-expressions">W3C </a>   </h3>

<p>General syntax is 
<pre>some <b>variable</b> in //xpath  satisfies (boolean expression using <b>$variable</b>)</pre>

 Returns true if at least one selection satisfies the
criterion. E.g. to search this document to make sure that at least one
h3 links out to the xpath Working Draft,
<tt>http://www.w3.org/TR/xpath20</tt>. The expression is:</p>

<pre>
  &lt;xsl:if test="$x in //h3/a/@href satisfies (contains($x,'http://www.w3.org/TR/xpath20'))">
Yes, at least one h3 satisfies the condition
</pre>

<p>This gives <xsl:if test="some $x in //h3/a/@href satisfies (contains ($x,'http://www.w3.org/TR/xpath20'))">
<b>Yes, at least one h3 satisfies the condition</b>
</xsl:if>
</p>

<p>Range expressions could be useful here too. E.g.</p>

<pre>
&lt;xsl:if test="some $x in (10, 1 to 4) satisfies ($x = 3)">
  Shows up as true, i.e. the range value contains 3.
&lt;/xsl:if>
</pre>
<p> The result is <b>
<xsl:if test="some $x in (10, 1 to 4) satisfies ($x = 3)">
  Shows up as true, i.e. the range value contains 3.
</xsl:if>
</b>

<br />
  Can also be used in conjunction with the predicates to act as a filter <br />
  <pre>
&lt;xsl:value-of select="(1 to 30)[. mod 5 eq 0]" separator=", "/>

</pre>
gives: <xsl:value-of select="(1 to 30)[. mod 5 eq 0]" separator=", "/>
</p>

<h3 id="cSeq">union and intercept operators. Combining sequences of node-sets  <a href="http://www.w3.org/TR/xpath20/#combining_seq">W3C </a>   </h3>

<p>The Union, Intercept and except operators work to combine sets.</p>

<pre>
&lt;xsl:variable name="a" select="(//h3)[position() &lt; 3]"/>
&lt;xsl:variable name="b" select="(//h3)[(position() > 2) and (position() &lt; 5)]"/>
&lt;xsl:variable name="c" select="(//h3)[(position() > 3)  and  (position() &lt; 6)]"/>
&lt;xsl:variable name="all" select="//h3"/>
</pre>
<xsl:variable name="a" select="(//h3)[position() &lt; 3]" as="item()*"/>
<xsl:variable name="b" select="(//h3)[(position() > 2) and (position() &lt; 5)]"/>
<xsl:variable name="c" select="(//h3)[(position() > 3)  and  (position() &lt; 6)]"/>
<xsl:variable name="all" select="//h3"/>

<p> Note the variable definition. I was corrected by Mike. <br />
<pre>&lt;xsl:variable name="a" select="(//h3)[position() &lt; 3]"/></pre>

 provides the document position of the first two h3 elements. Note the
(//h3). There can be lots of h3 elements in the document all satisfying //h3[1].
 <br />
Using 'count()' on these variable gives: <br/>
a has <xsl:value-of select="count($a)"/> elements<br />
b has <xsl:value-of select="count($b)"/> elements<br />
c has <xsl:value-of select="count($c)"/> elements<br />
</p>
<p>exploring $c to find its position within the document using
<pre>
&lt;xsl:for-each select="$c">
 Value is:  &lt;xsl:value-of select="index-of($all, .)"/>...  &lt;xsl:value-of select="text()[1]"/>
&lt;/xsl:for-each>
</pre>

<xsl:for-each select="$c">
Value is:  <xsl:value-of select="index-of($all, .)"/> ... <xsl:value-of select="text()[1]"/> <br />
</xsl:for-each>


</p>
<p>Using the union function, as in 
<pre>
There are &lt;xsl:value-of select="count($a union $b)"/>&lt;br />
  &lt;xsl:for-each select="($a union $a)">
Number     &lt;xsl:value-of select="index-of($all, .)"/>is  &lt;xsl:value-of select="text()[1]"/> in the Union.
  &lt;/xsl:for-each>
</pre>


 <br />
There are <xsl:value-of select="count($a union $b)"/> in the Union.<br />
  <xsl:for-each select="($a union $a)">
Number    <xsl:value-of select="index-of($all, .)"/> is  <xsl:value-of select="text()[1]"/> <br />
  </xsl:for-each>
</p>

<p>Intersection of  b and c using:

<pre>
There are &lt;xsl:value-of select="count($b intersect $c)"/> in the intersection&lt;br />
  &lt;xsl:for-each select="($b intersect $c)">
Number  &lt;xsl:value-of select="index-of($all, .)"/> is  &lt;xsl:value-of select="text()[1]"/> &lt;br />
  &lt;/xsl:for-each>
</pre>

There are <xsl:value-of select="count($b intersect $c)"/> in the intersection<br />
  <xsl:for-each select="($b intersect $c)">
Number     <xsl:value-of select="index-of($all, .)"/> is  <xsl:value-of select="text()[1]"/> <br />
  </xsl:for-each>
</p>

<p>$b except $c, as in 
<pre>
There are &lt;xsl:value-of select="count($b except $c)"/>&lt;br />
  &lt;xsl:for-each select="($b except $c)">
Number &lt;xsl:value-of select="index-of($all, .)"/> is    &lt;xsl:value-of select="text()[1]"/> &lt;br />
  &lt;/xsl:for-each>
</pre>


There are <xsl:value-of select="count($b except $c)"/><br />
  <xsl:for-each select="($b except $c)">
Number <xsl:value-of select="index-of($all, .)"/> is    <xsl:value-of select="text()[1]"/> <br />
  </xsl:for-each>
</p>



<h3 id="ins">insert() Insert-before  function <a href="http://www.w3.org/TR/xquery-operators/#func-insert-before">W3C </a>   </h3>

<p>Given some sequence, insert (or remove )an item at a given position. <br />

&lt;xsl:value-of select="insert-before($target-seq, $position, $what-to-insert)"/><br />

E.g. given a sequence</p>
<xsl:variable name="target-seq" select="(1,2,3,4,7)"/>
<xsl:variable name="what-to-insert" select="(5,6)"/>
<xsl:variable name="position" select="5"/>

<pre>
&lt;xsl:variable name="target-seq" select="(1,2,3,4,7)"/>
&lt;xsl:variable name="what-to-insert" select="(5,6)"/>
&lt;xsl:variable name="position" select="4"/>
</pre>
<p>
Inserting at position 4, 
  <pre>
&lt;xsl:variable name="result"  
select="insert-before($target-seq, $position, $what-to-insert)"/> 
</pre>
gives <br />
 <!-- 7.5 was insert, now insert-before  -->
<xsl:variable name="result"  select="insert-before($target-seq, $position, $what-to-insert)"/>


(<xsl:value-of select="$result" separator=", "/>)   - the (5,6 ) is inserted.
<br />
</p>


<h3 id="rem">remove() Remove functions <a
href="http://www.w3.org/TR/xquery-operators/#func-remove">W3C </a>
</h3>


<p>
  Similarly, removing the 5th element <br />
<xsl:variable name="result1"  select="remove($target-seq, 5)"/> 

<pre>
&lt;xsl:variable name="result1"  select="remove($target-seq, 5)"/> 
</pre>
gives
(<xsl:value-of select="$result1" separator=", "/>) <br />

<h3 id="subs">Subsequence  functions <a
href="http://www.w3.org/TR/xquery-operators/#func-subsequence">W3C </a>
</h3>

As with strings, there is also the subsequence function, 
<pre>
&lt;xsl:variable name='ss' select = subsequence( $target-seq $position $length)"/>
</pre>
which returns the sub-sequence starting at $position and extending to $position+$length. <br />
E.g. if $length is 2 and $position is 3 then 
<pre>
&lt;xsl:variable name="result2" select="subsequence($target-seq, 3, 2)"/> 
(&lt;xsl:value-of select="$result2" separator=", "/>) 
</pre>

<xsl:variable name="result2" select="subsequence($target-seq, 3, 2)"/> <br />
gives (<xsl:value-of select="$result2" separator=", "/>) <br />



</p>







<h3 id="numeric">avg() max() min() sum() abs() - the Numeric functions.<a href="http://www.w3.org/TR/xquery-operators/#d1e5200">W3C </a>   </h3>

<p>Given a  numeric variable:

</p>
<pre>
&lt;xsl:variable name="n1" select="(3,4,6,8,-1)"/>

</pre>
<p>We can play with them just a little more: <br />
<xsl:variable name="n1" select="(3,4,6,8,-1)"/>
E.g. The number of items in a sequence, count($n1) gives <xsl:value-of select="count($n1)"/><br />
The average, avg($n1) gives <xsl:value-of select="avg($n1)"/> <br />
The  max($n1) gives gives <xsl:value-of select="max($n1)"/> <br />
The  min($n1) gives <xsl:value-of select="min($n1)"/> <br />
The  sum($n1) gives <xsl:value-of select="sum($n1)"/> <br />
The absolute value of the last item gives <xsl:value-of select="abs($n1[last()])"/>
There is some type information there, but it works well without it.
</p>


<h3 id="lnk">idref() - Linking functions. <a href="http://www.w3.org/TR/xquery-operators/#func-xpath-idref">W3C </a>   </h3>

<p>idref(String) provides a source node for the value passed in as a
parameter. E.g. this heading is linked to from the end of the
document. So, using this function, I can return the content of the
element linking to it, i.e.
<pre>
[&lt;xsl:value-of select="idref('lnk')/../text()"/>]

The element having idref 'lnk' contains  [<xsl:value-of select="idref('lnk')/../text()"/>]
</pre>



</p>



<h3 id="for">for loop. <a href="http://www.w3.org/TR/xpath20/#id-for-expressions">W3C  </a>  </h3>

<p>The for loop is provided in xpath, with syntax as shown below:</p>

<pre>
for $x in (expression) return (expression)
</pre>

<p>Using 
<pre>
&lt;xsl:for-each select="for $i in ((//h3)[position() &lt; 3]) return ($i/text()[1])">
Value: &lt;xsl:value-of select="."/>
 &lt;/xsl:for-each>
</pre>
gives
<b> <xsl:for-each select="for $i in ((//h3)[position() &lt; 3]) return ($i/text()[1])">
Value: <xsl:value-of select="."/>
 <br />
 </xsl:for-each>
</b>
 This example iterates over the sequence, returning the text(). 
</p>

<p>A better example might be to use the for statement to generate a
sequence, then to operate on that sequence using a function which
takes that as its input. For example; I wanted to find the max number
of columns in a table, so in the template for the column, I had </p>

<pre>
max(for $i in ../../row return count($i/*))
</pre>

<p>this for statement returned a sequence, and the max function
provides the maximum number in that sequence.

</p>

<p style="color:red">Note: Unlike pretty much every other xpath or
xslt construct, for does not change the current node so ".", relative
path expressions, etc all do not work as you might expect: they all
stay relative to whatever was the context outside the for.  <i>DC Apr
03.</i>

</p>

<h3 id="types">as - Creating variables of a given type  <a href="http://www.w3.org/TR/xslt20/#element-variable">W3C</a>  </h3>

<p>Creating a variable of specific types, using the 'as' attribute. <br />
E.g. 
<pre>
&lt;xsl:variable name="ls" as="item()*"
  &lt;xsl:sequence select="(2,5,6,7,8)" />
    &lt;/xsl:variable>
</pre>
 <!-- 7.5, was 'as item*' -->
<xsl:variable name="ls" as="item()*">
  <xsl:sequence  select="(2,5,6,7,8)" />
  </xsl:variable>

  <br />
 gives <xsl:value-of select="$ls" separator=", "/>
<br />
  Similarly, using source document content: <br />
E.g.
  <pre>
 &lt;xsl:variable name="ls1" 
  select="for $i in (//h3[position() &lt; 6]) return string-length($i) "/><br />
  </pre>

  <xsl:variable name="ls1" 
      select="for $i in ((//h3)[position() &lt; 6]) return string-length($i) "/>
 returns  <xsl:value-of select="$ls1" separator=", "/>

 <br />
Note: MK: 17 3 03. With Saxon 7.4 and with the November XSLT 2.0 spec, the only way to
create a variable whose value is a sequence is using the select
attribute.

   <br />
 
Dates may be formed using 

     <pre>
&lt;xsl:variable name='today' select='xs:date("2003-06-25")'/>
     </pre>
     <xsl:variable name='today' select='xs:date("2003-06-25")'/>
   <xsl:variable name='Before' select='xs:date("2001-08-25")'/>
   Then used, 

   <pre>
&lt;xsl:value-of select="$today" /> 
</pre>
which gives
Today is <xsl:value-of select="$today"/> <br />
Difference  is <xsl:value-of select="$Before - $today"/>
</p>


<h3 id="qchn">"(&amp;quot;) character nesting: <a href="http://www.w3.org/TR/xpath20/#doc-StringLiteral">W3C </a> </h3>

<p>String content can now contain an easier mix of double (&#x0022;)
and single quote (&#x2019;) characters. (Note they are spread out here
for clarity.) the principle is to 'escape' a quote with another
one. <br />

E.g. 
<pre>&lt;xsl:value-of select=' "He said, " " Go! " " " '/> 
</pre>
gives: <b>
<xsl:value-of select='"He said, ""Go!""" '/></b>

</p>


<h3 id="rv">some and every $x - Range variables. <a href="http://www.w3.org/TR/xpath20/#id-quantified-expressions">W3C</a>   </h3>

<p>These are 'variables' which take the form of a
sequence of items, and are created using the for, some and every
syntax already mentioned above. <br />

The general form is 'some $variable in Expression satisfies
SingleExpression' E.g.

<pre>
1 &lt;xsl:variable name="rv1" select="(1,3,6,6 to 16)"/> 
or 
2 &lt;xsl:variable name='rv2' select="some $i in (//h3) satisfies (string-length($i) &lt; 12)"/>
or 
3 &lt;xsl:variable name='rv3' select="every $i in (//h3) satisfies (string-length($i) &gt; 5) "/>
</pre>

Gives: 
<xsl:variable name="rv1" select="for $i in (1,3,6,6 to 16) return $i * 2"/> <br /> 
<xsl:variable name='rv2' select="some $i in (//h3) satisfies (string-length($i) &lt; 20) "/>
<xsl:variable name='rv3' select="every $i in (//h3) satisfies (string-length($i) &gt; 5) "/>
<xsl:variable name='rv4' select="some $i in $rv1 satisfies ($i = 6) "/>




 <br /> 
and accessed using, perhaps, value-of with a separator attribute  <br /> 

rv1 gives:   <xsl:value-of select="$rv1" separator="| "/>  <br /> 
rv2 gives:   <xsl:value-of select="$rv2" separator="| "/>  <br /> 
rv3 gives:   <xsl:value-of select="$rv3" separator="| "/>  <br /> 
rv4 gives:   <xsl:value-of select="$rv4" separator="| "/>

</p>

<p>The range variables can also be used as predicates. </p>

<pre>
&lt;xsl:for-each  select="(//h3)[@id][some $x in position() satisfies ($x lt 3)]">
  &lt;xsl:value-of select="@id"/> <xsl:text> | </xsl:text>
&lt;/xsl:for-each>
</pre>



<p>This gives: 
<!--<xsl:for-each  select="(//h3)[@id][position() = 1 to 2]"> -->
<xsl:for-each  select="(//h3)[@id][some $x in position() satisfies ($x lt 3)]">
  <b>  <xsl:value-of select="@id"/> <xsl:text> | </xsl:text> </b>
</xsl:for-each>
 which is the id value of the first two h3 elements. 
</p>
<p>And finally, a use to retrieve a fixed length string. This could replace the pad function often requested, if wrapped in a function call </p>

<pre>
&lt;xsl:variable name="param" select="5"/>
&lt;xsl:value-of select="string-join(for $i in 1 to $param return 'X','')"/>

gives
<xsl:variable name="param" select="5"/>
<b><xsl:value-of select="string-join(for $i in 1 to $param return 'X','')"/></b>
</pre>
<p>I.e. It returns a $param length string.</p> 


<h3 id="cpy-of-ns">xsl:copy-of with / without namespace <a href="http://www.w3.org/TR/xslt20/#copy-of">W3C</a></h3>


<p>View source for this xsl:copy, with  namespace</p>
<pre>
1. Using
&lt;xsl:for-each select="document('')//dp:distinct">
&lt;xsl:copy >
  &lt;xsl:copy-of select="*|@*"   <b>copy-namespaces = "yes"</b>  />  
&lt;/xsl:copy>
&lt;/xsl:for-each>
and 
2.
&lt;xsl:for-each select="document('')//dp:distinct">
&lt;xsl:copy >
&lt;xsl:copy-of select="*|@*"  <b>  copy-namespaces = "no" </b>/>  
&lt;/xsl:copy>
&lt;/xsl:for-each>


</pre>

<p>This gives Resulting content - which won't show correctly in a browser.</p>
<p style="color:green;align:end">
<xsl:for-each select="document('')//dp:distinct">
<xsl:copy >
  <xsl:copy-of select="*|@*"   copy-namespaces = "yes"   />  
</xsl:copy>
</xsl:for-each>
<br />
<xsl:for-each select="document('')//dp:distinct">
<xsl:copy>
    <xsl:copy-of select="*|@*"   copy-namespaces = "no"  />  
</xsl:copy>
</xsl:for-each>

</p>

<pre>
&lt;dp:distinct xmlns:dp="http://www.dpawson.co.uk/namespace" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns:pref="http://www.dpawson.co.uk" 
  xmlns:saxon="http://saxon.sf.net/" 
  xmlns:d="rnib.org.uk/tbs#">
     &lt;dp:val1>Single value&lt;/dp:val1>
     &lt;dp:val1>Single value&lt;/dp:val1>
     &lt;dp:val1>Single value with a difference.&lt;/dp:val1>
 &lt;/dp:distinct>

</pre>

<p>And for the second one</p>

<pre>
&lt;dp:distinct 
  xmlns:dp="http://www.dpawson.co.uk/namespace">
  &lt;dp:val1>Single value&lt;/dp:val1>
  &lt;dp:val1>Single value&lt;/dp:val1>
  &lt;dp:val1>Single value with a difference.&lt;/dp:val1>
&lt;/dp:distinct>
</pre>

<p>Which is quite a difference? The only ns in the second one I'd agree is required.</p>




<p>View source for actual output</p>


<p> The second is restricted to the dp namespace, the first has all ns
included. Seems about right.</p>

<h3 id="cp2string">codepoints-to-string() <a href="http://www.w3.org/TR/xquery-operators/#func-codepoints-to-string">W3C</a></h3>
<p>Converts the input Unicode code points to a string. DC gave me
the example of using it to reverse a string!
<pre>
&lt;xsl:variable name="in" select="'Now is the time'"/>
&lt;xsl:value-of select="codepoints-to-string(reverse(string-to-codepoints($in)))"/>

Gives: 
</pre>

<xsl:variable name="in" select="'Now is the time'"/>
<b>
<xsl:value-of select="codepoints-to-string(reverse(string-to-codepoints($in)))"/>
</b>
</p>
<p>A simpler case.  Given the sequence (41,42,x5E,30), the function converts this to <xsl:value-of 
select="codepoints-to-string((65,66,94,48))"/></p>

<h3 id="string2cp">string-to-codepoints() <a href="http://www.w3.org/TR/xquery-operators/#func-codepoints-to-string">W3C</a></h3>
<p>Provides the reciprocal conversion, converting a string
to a sequence of codepoints</p>
<pre>
&lt;xsl:value-of select="string-to-codepoints('Now is the time')"/>
</pre>
<xsl:value-of select="string-to-codepoints('Now is the time')"/>


<h3 id="enc4uri">encode-for-uri() <a href="http://www.w3.org/TR/xpath-functions#func-encode-for-uri">W3C</a></h3>

<p> This function applies the URI escaping rules defined in section 2
of RFC 3986 to the string supplied</p>
<p>E.g. encode-for-uri ("http://www.example.com/00/Weather/CA/Los%20Angeles#ocean") gives <br /><xsl:value-of select='encode-for-uri ("http://www.example.com/00/Weather/CA/Los%20Angeles#ocean")'/></p>
<p>See also <a href="http://www.w3.org/TR/xpath-functions#func-iri-to-uri">W3C</a>, which has the variant function 'iri-to-uri()' </p>

<h3 id="cpeq">codepoint-equal() <a href="http://www.w3.org/TR/xquery-operators/#func-codepoint-equal">W3C</a></h3>

<p>Compares two strings according to the Unicode codepoint
collation. Usage</p>

<pre>&lt;xsl:if test="codepoint-equal($s1,$s2)">
</pre>

<h3 id="collection">collection(). Seems to return a number of xml instance. See <a href="http://www.w3.org/TR/xpath-functions#func-collection">W3C</a> for more. Leakage from XQuery perhaps?</h3>

<h3 id="upi">unparsed-entity-uri()  <a href="http://www.w3.org/TR/xslt20/#unparsed-entity-uri">W3C </a>  </h3>

<p>Using the definition 
<pre>
&lt;!ENTITY thisFile SYSTEM "ndata.txt" NDATA txt>
</pre>

and a use of <br />
<pre>
&lt;xsl:value-of select="unparsed-entity-uri('thisFile')"/>
</pre>
</p>


<p> Returned value is [<xsl:value-of
select="unparsed-entity-uri('thisFile')"/> ]... which is the value of
the entity, not its content.  </p>

<h3 id="upt">unparsed-text() - get the contents of a text file. <a href="http://www.w3.org/TR/xslt20/#unparsed-text">W3C</a> </h3>


<p> Definition, 
  <pre>&lt;xsl:value-of select="unparsed-text($strng,$encoding)"/></pre>
 treats
the first parameter as a sequence of uri's. The second is the
encoding. Using it 
  <pre> 
&lt;xsl:value-of
select="unparsed-text('ndata.txt','utf-8')"/>
</pre>

with a minimal file which contains some content,
returns the contents of that file: <br />  </p> <pre>
  <xsl:value-of select="unparsed-text('ndata.txt','utf-8')"/>

</pre>
<p>Hence this is the one to use when you want to include plain text or similar. NDATA

implies that the parser informs the processing system that it has encountered an
NDATA entity reference and gives it the relevant information. It is up
to the processing system to decide what to do with it. It is not parsed as XML </p> <h3
id='rdoc'>xsl:result-document - Indirect use <a
href="http://www.w3.org/TR/xslt20/#element-result-document">W3C
</a> </h3>

<p>As <a href="#resDoc">above</a>, this uses the
<tt>xsl:result-document</tt>, but here its referenced from the
<tt>xsl:output</tt> element, using the <tt>format</tt> attribute to
reference the <tt>xsl:result-document</tt>.</p>

<pre>
As in &lt;xsl:result-document 
              href="newfile.xml" 
              format="newFormat"
               validation="preserve"> 

(then, as a top level element)
  &lt;xsl:output name="newFormat" method="xml" indent="yes"/> </pre>
<p>See file newfile.xml for output. Note that the format is specified
in an output statement, which now has a name</p>
 <!-- 7.5 type-information="preserve" removed from result-document  -->
<xsl:result-document 
              href="newfile.xml" 
              format="newFormat"
              >  <!-- chx to validation= DPXS -->
  <document>
    <content>Some output content using result-document</content>
  </document>
</xsl:result-document>



<hr />

<h3 id="fna">function-available() - Function Availability. Does your process support this?  <a href="http://www.w3.org/TR/xslt20/#function-function-available">W3C </a>  </h3>
<p>A list of functions, tested for availability. Check by running the stylesheet. This run on <xsl:value-of select="dp:pretty-date($date)"/>. (Note: There are 
<xsl:value-of select="count(id('fns')/li)"/> functions in total</p>
<ul id="fns">

<li><xsl:value-of select="if(function-available('abs')) then 'abs() OK' else 'abs() missing'"/></li>

 
<li><xsl:value-of select="if (function-available('adjust-date-to-timezone')) then 'adjust-date-to-timezone() OK' else 'adjust-date-to-timezone() missing'"/></li>

<li><xsl:value-of select="if (function-available('adjust-dateTime-to-timezone')) then 'adjust-dateTime-to-timezone() OK' else 'adjust-dateTime-to-timezone() missing'"/></li>

<li><xsl:value-of select="if (function-available('adjust-time-to-timezone')) then 'adjust-time-to-timezone() OK' else 'adjust-time-to-timezone() missing'"/></li>

<li><xsl:value-of select="if (function-available('avg')) then 'avg() OK' else 'avg() missing'"/></li>

<li><xsl:value-of select="if (function-available('base-uri')) then 'base-uri() OK' else 'base-uri() missing'"/></li>
<li><xsl:value-of select="if (function-available('boolean')) then 'boolean() OK' else 'boolean() missing'"/></li>
<li><xsl:value-of select="if (function-available('ceiling')) then 'ceiling() OK' else 'ceiling() missing'"/></li>
<li><xsl:value-of select="if (function-available('codepoint-equal')) then 'codepoint-equal() OK' else 'codepoint-equal() missing'"/></li>
<li><xsl:value-of select="if (function-available('codepoints-to-string')) then 'codepoints-to-string() OK' else 'codepoints-to-string() missing'"/></li>
<li><xsl:value-of select="if (function-available('collection')) then 'collection() OK' else 'collection() missing'"/></li>
<li><xsl:value-of select="if (function-available('compare')) then 'compare() OK' else 'compare() missing'"/></li>
<li><xsl:value-of select="if (function-available('concat')) then 'concat() OK' else 'concat() missing'"/></li>
<li><xsl:value-of select="if (function-available('contains')) then 'contains() OK' else 'contains() missing'"/></li>
<li><xsl:value-of select="if (function-available('count')) then 'count() OK' else 'count() missing'"/></li>
<li><xsl:value-of select="if (function-available('current-date')) then 'current-date() OK' else 'current-date() missing'"/></li>
<li><xsl:value-of select="if (function-available('current-dateTime')) then 'current-dateTime() OK' else 'current-dateTime() missing'"/></li>
<li><xsl:value-of select="if (function-available('current-time')) then 'current-time() OK' else 'current-time() missing'"/></li>
<li><xsl:value-of select="if (function-available('data')) then 'data() OK' else 'data() missing'"/></li>
<li><xsl:value-of select="if (function-available('dateTime')) then 'dateTime() OK' else 'dateTime() missing'"/></li>
<li><xsl:value-of select="if (function-available('day-from-date')) then 'day-from-date() OK' else 'day-from-date() missing'"/></li>
<li><xsl:value-of select="if (function-available('day-from-dateTime')) then 'day-from-dateTime() OK' else 'day-from-dateTime() missing'"/></li>
<li><xsl:value-of select="if (function-available('days-from-duration')) then 'days-from-duration() OK' else 'days-from-duration() missing'"/></li>
<li><xsl:value-of select="if (function-available('deep-equal')) then 'deep-equal() OK' else 'deep-equal() missing'"/></li>
<li><xsl:value-of select="if (function-available('default-collation')) then 'default-collation() OK' else 'default-collation() missing'"/></li>
<li><xsl:value-of select="if (function-available('distinct-values')) then 'distinct-values() OK' else 'distinct-values() missing'"/></li>
<li><xsl:value-of select="if (function-available('doc')) then 'doc() OK' else 'doc() missing'"/></li>
<li><xsl:value-of select="if (function-available('doc-available')) then 'doc-available() OK' else 'doc-available() missing'"/></li>
<li><xsl:value-of select="if (function-available('document-uri')) then 'document-uri() OK' else 'document-uri() missing'"/></li>
<li><xsl:value-of select="if (function-available('empty')) then 'empty() OK' else 'empty() missing'"/></li>
<li><xsl:value-of select="if (function-available('encode-for-uri')) then 'encode-for-uri() OK' else 'encode-for-uri() missing'"/></li>
<li><xsl:value-of select="if (function-available('ends-with')) then 'ends-with() OK' else 'ends-with() missing'"/></li>
<li><xsl:value-of select="if (function-available('error')) then 'error() OK' else 'error() missing'"/></li>
<li><xsl:value-of select="if (function-available('escape-html-uri')) then 'escape-html-uri() OK' else 'escape-html-uri() missing'"/></li>
<li><xsl:value-of select="if (function-available('exactly-one')) then 'exactly-one() OK' else 'exactly-one() missing'"/></li>
<li><xsl:value-of select="if (function-available('exists')) then 'exists() OK' else 'exists() missing'"/></li>
<li><xsl:value-of select="if (function-available('false')) then 'false() OK' else 'false() missing'"/></li>
<li><xsl:value-of select="if (function-available('floor')) then 'floor() OK' else 'floor() missing'"/></li>
<li><xsl:value-of select="if (function-available('hours-from-dateTime')) then 'hours-from-dateTime() OK' else 'hours-from-dateTime() missing'"/></li>
<li><xsl:value-of select="if (function-available('hours-from-duration')) then 'hours-from-duration() OK' else 'hours-from-duration() missing'"/></li>
<li><xsl:value-of select="if (function-available('hours-from-time')) then 'hours-from-time() OK' else 'hours-from-time() missing'"/></li>
<li><xsl:value-of select="if (function-available('id')) then 'id() OK' else 'id() missing'"/></li>
<li><xsl:value-of select="if (function-available('idref')) then 'idref() OK' else 'idref() missing'"/></li>
<li><xsl:value-of select="if (function-available('implicit-timezone')) then 'implicit-timezone() OK' else 'implicit-timezone() missing'"/></li>
<li><xsl:value-of select="if (function-available('in-scope-prefixes')) then 'in-scope-prefixes() OK' else 'in-scope-prefixes() missing'"/></li>
<li><xsl:value-of select="if (function-available('index-of')) then 'index-of() OK' else 'index-of() missing'"/></li>
<li><xsl:value-of select="if (function-available('insert-before')) then 'insert-before() OK' else 'insert-before() missing'"/></li>
<li><xsl:value-of select="if (function-available('iri-to-uri')) then 'iri-to-uri() OK' else 'iri-to-uri() missing'"/></li>
<li><xsl:value-of select="if (function-available('lang')) then 'lang() OK' else 'lang() missing'"/></li>
<li><xsl:value-of select="if (function-available('last')) then 'last() OK' else 'last() missing'"/></li>
<li><xsl:value-of select="if (function-available('local-name')) then 'local-name() OK' else 'local-name() missing'"/></li>
<li><xsl:value-of select="if (function-available('local-name-from-QName')) then 'local-name-from-QName() OK' else 'local-name-from-QName() missing'"/></li>
<li><xsl:value-of select="if (function-available('lower-case')) then 'lower-case() OK' else 'lower-case() missing'"/></li>
<li><xsl:value-of select="if (function-available('matches')) then 'matches() OK' else 'matches() missing'"/></li>
<li><xsl:value-of select="if (function-available('max')) then 'max() OK' else 'max() missing'"/></li>
<li><xsl:value-of select="if (function-available('min')) then 'min() OK' else 'min() missing'"/></li>
<li><xsl:value-of select="if (function-available('minutes-from-dateTime')) then 'minutes-from-dateTime() OK' else 'minutes-from-dateTime() missing'"/></li>
<li><xsl:value-of select="if (function-available('minutes-from-duration')) then 'minutes-from-duration() OK' else 'minutes-from-duration() missing'"/></li>
<li><xsl:value-of select="if (function-available('minutes-from-time')) then 'minutes-from-time() OK' else 'minutes-from-time() missing'"/></li>
<li><xsl:value-of select="if (function-available('month-from-date')) then 'month-from-date() OK' else 'month-from-date() missing'"/></li>
<li><xsl:value-of select="if (function-available('month-from-dateTime')) then 'month-from-dateTime() OK' else 'month-from-dateTime() missing'"/></li>
<li><xsl:value-of select="if (function-available('months-from-duration')) then 'months-from-duration() OK' else 'months-from-duration() missing'"/></li>
<li><xsl:value-of select="if (function-available('name')) then 'name() OK' else 'name() missing'"/></li>
<li><xsl:value-of select="if (function-available('namespace-uri')) then 'namespace-uri() OK' else 'namespace-uri() missing'"/></li>
<li><xsl:value-of select="if (function-available('namespace-uri-for-prefix')) then 'namespace-uri-for-prefix() OK' else 'namespace-uri-for-prefix() missing'"/></li>
<li><xsl:value-of select="if (function-available('namespace-uri-from-QName')) then 'namespace-uri-from-QName() OK' else 'namespace-uri-from-QName() missing'"/></li>
<li><xsl:value-of select="if (function-available('nilled')) then 'nilled() OK' else 'nilled() missing'"/></li>
<li><xsl:value-of select="if (function-available('node-name')) then 'node-name() OK' else 'node-name() missing'"/></li>
<li><xsl:value-of select="if (function-available('normalize-space')) then 'normalize-space() OK' else 'normalize-space() missing'"/></li>
<li><xsl:value-of select="if (function-available('normalize-unicode')) then 'normalize-unicode() OK' else 'normalize-unicode() missing'"/></li>
<li><xsl:value-of select="if (function-available('not')) then 'not() OK' else 'not() missing'"/></li>
<li><xsl:value-of select="if (function-available('number')) then 'number() OK' else 'number() missing'"/></li>
<li><xsl:value-of select="if (function-available('one-or-more')) then 'one-or-more() OK' else 'one-or-more() missing'"/></li>
<li><xsl:value-of select="if (function-available('position')) then 'position() OK' else 'position() missing'"/></li>
<li><xsl:value-of select="if (function-available('prefix-from-QName')) then 'prefix-from-QName() OK' else 'prefix-from-QName() missing'"/></li>
<li><xsl:value-of select="if (function-available('QName')) then 'QName() OK' else 'QName() missing'"/></li>
<li><xsl:value-of select="if (function-available('remove')) then 'remove() OK' else 'remove() missing'"/></li>
<li><xsl:value-of select="if (function-available('replace')) then 'replace() OK' else 'replace() missing'"/></li>
<li><xsl:value-of select="if (function-available('resolve-QName')) then 'resolve-QName() OK' else 'resolve-QName() missing'"/></li>
<li><xsl:value-of select="if (function-available('resolve-uri')) then 'resolve-uri() OK' else 'resolve-uri() missing'"/></li>
<li><xsl:value-of select="if (function-available('reverse')) then 'reverse() OK' else 'reverse() missing'"/></li>
<li><xsl:value-of select="if (function-available('root')) then 'root() OK' else 'root() missing'"/></li>
<li><xsl:value-of select="if (function-available('round')) then 'round() OK' else 'round() missing'"/></li>
<li><xsl:value-of select="if (function-available('round-half-to-even')) then 'round-half-to-even() OK' else 'round-half-to-even() missing'"/></li>
<li><xsl:value-of select="if (function-available('seconds-from-dateTime')) then 'seconds-from-dateTime() OK' else 'seconds-from-dateTime() missing'"/></li>
<li><xsl:value-of select="if (function-available('seconds-from-duration')) then 'seconds-from-duration() OK' else 'seconds-from-duration() missing'"/></li>
<li><xsl:value-of select="if (function-available('seconds-from-time')) then 'seconds-from-time() OK' else 'seconds-from-time() missing'"/></li>
<li><xsl:value-of select="if (function-available('starts-with')) then 'starts-with() OK' else 'starts-with() missing'"/></li>
<li><xsl:value-of select="if (function-available('static-base-uri')) then 'static-base-uri() OK' else 'static-base-uri() missing'"/></li>
<li><xsl:value-of select="if (function-available('string')) then 'string() OK' else 'string() missing'"/></li>
<li><xsl:value-of select="if (function-available('string-join')) then 'string-join() OK' else 'string-join() missing'"/></li>
<li><xsl:value-of select="if (function-available('string-length')) then 'string-length() OK' else 'string-length() missing'"/></li>
<li><xsl:value-of select="if (function-available('string-to-codepoints')) then 'string-to-codepoints() OK' else 'string-to-codepoints() missing'"/></li>
<li><xsl:value-of select="if (function-available('subsequence')) then 'subsequence() OK' else 'subsequence() missing'"/></li>
<li><xsl:value-of select="if (function-available('substring')) then 'substring() OK' else 'substring() missing'"/></li>
<li><xsl:value-of select="if (function-available('substring-after')) then 'substring-after() OK' else 'substring-after() missing'"/></li>
<li><xsl:value-of select="if (function-available('substring-before')) then 'substring-before() OK' else 'substring-before() missing'"/></li>
<li><xsl:value-of select="if (function-available('sum')) then 'sum() OK' else 'sum() missing'"/></li>
<li><xsl:value-of select="if (function-available('timezone-from-date')) then 'timezone-from-date() OK' else 'timezone-from-date() missing'"/></li>
<li><xsl:value-of select="if (function-available('timezone-from-dateTime')) then 'timezone-from-dateTime() OK' else 'timezone-from-dateTime() missing'"/></li>
<li><xsl:value-of select="if (function-available('timezone-from-time')) then 'timezone-from-time() OK' else 'timezone-from-time() missing'"/></li>
<li><xsl:value-of select="if (function-available('tokenize')) then 'tokenize() OK' else 'tokenize() missing'"/></li>
<li><xsl:value-of select="if (function-available('trace')) then 'trace() OK' else 'trace() missing'"/></li>
<li><xsl:value-of select="if (function-available('translate')) then 'translate() OK' else 'translate() missing'"/></li>
<li><xsl:value-of select="if (function-available('true')) then 'true() OK' else 'true() missing'"/></li>
<li><xsl:value-of select="if (function-available('unordered')) then 'unordered() OK' else 'unordered() missing'"/></li>
<li><xsl:value-of select="if (function-available('upper-case')) then 'upper-case() OK' else 'upper-case() missing'"/></li>
<li><xsl:value-of select="if (function-available('year-from-date')) then 'year-from-date() OK' else 'year-from-date() missing'"/></li>
<li><xsl:value-of select="if (function-available('year-from-dateTime')) then 'year-from-dateTime() OK' else 'year-from-dateTime() missing'"/></li>
<li><xsl:value-of select="if (function-available('years-from-duration')) then 'years-from-duration() OK' else 'years-from-duration() missing'"/></li>
<li><xsl:value-of select="if (function-available('zero-or-one')) then 'zero-or-one() OK' else 'zero-or-one() missing'"/></li>

</ul>



 <h3 id="ch-map">xsl:character-map <a href="http://www.w3.org/TR/xslt20/#element-character-map">W3C</a> </h3> 




 <pre>
&lt;-- Note that this is a top level element -->

&lt;xsl:character-map name="html">
  &lt;xsl:output-character character="&amp;#160;"
                        string="&amp;amp;nbsp;" />
  &lt;!-- tabs as four spaces -->
  &lt;xsl:output-character character="&amp;#x9;" string="    " />

&lt;/xsl:character-map>

 </pre>
 <p>Another oft-requested feature. Translate character x into string
Y, or even entity Z.

 In the example: Non breaking space to the entity &amp;nbsp; <br />
 and a tab character into 4 spaces.  <br />

When the &lt;xsl:output element is used, the attribute
character-map="name" is used to reference the mappings.
 <pre>
   &lt;xsl:output method="xhtml" use-character-map="html" indent="yes"/>

</pre> would invoke the above character map. We can now use this to
get our beloved entities into the output file without using DOE.

Implemented in  Saxon <xsl:value-of select="$saxonVsn"/>, but read the comments.



</p>





 <!-- <h3 id=""> <a href="">W3C</a> </h3> -->

<h3 id="ssName">Stylesheet and source document name+path <a href="http://www.w3.org/TR/xquery-operators/#func-base-uri">W3C</a> </h3>
<p> Using base-uri to obtain the stylesheet name as in 
<pre>
&lt;xsl:value-of select="base-uri(document(''))"/>
</pre>
 Gives <xsl:value-of select="base-uri(document(''))"/>


and for source document use 
<pre>&lt;xsl:value-of select="base-uri(.)"/>
</pre>
 gives <xsl:value-of select="base-uri(.)"/>, which happens to be the same in this case. Without a context, the '.' in this case, the function appears to return the stylesheet value.
</p>
<p>That's it... for version <xsl:value-of select="$ver"/>.</p>

<hr style="color:green; width:80%; size=8; noshade" />

<p style="color:red"> WARNING: You'll screw this up if you set xml:base prior to using this stylsheet.</p>


<h3 id="dxn">xpath-default-namespace()    <a href="http://www.w3.org/TR/xpath20/#dt-def-elemtype-ns">W3C</a></h3>

<p>Ever used an expression like 

<pre>value-of select="vis:Visiodocument/vis:Pages/vis:Page[0]/vis:shapes/vis:shape" </pre>
Where it appears to get longer and longer the more you type?
Help is at hand. Its now possible to abbreviate this, using 
<pre>
&lt;xsl:template match="Visiodocument/Pages/Page[0]/shapes/shape" xpath-default-namespace="vis">

  etc.
</pre>

For example to access a stylesheet template, use
<pre>
   &lt;xsl:template match="template" 
 default-xpath-namespace="http://www.w3.org/1999/XSL/Transform">
     [&lt;xsl:value-of select="value-of/@select" 
 default-xpath-namespace="http://www.w3.org/1999/XSL/Transform"/>]
   &lt;/xsl:template>

</pre> 

Note that the select attribute does not have to be
reverse-engineered, since this default xpath namespace does not apply
to attributes... even if its not clear in the specification.


 </p>



<h3 id="cast">Cast to another type <a href="http://www.w3.org/TR/xquery-operators/#constructor-functions">W3C</a> </h3>

<p> Also see <a
href="http://www.w3.org/TR/xquery-operators/#constructor-functions">Constructor
Functions for XML Schema Built-in Types </a>, a page or so down from
the link target, which is a list of types. Unsure if its complete.</p>


<p>It would appear almost impossible, despite the WG's assurances, to
avoid using data types and still gain the benefit of the good features
of XSLT 2.0. This section shows how to convert from one to another.

</p>
<p>See also <a href="http://www.w3.org/TR/xmlschema-2/#built-in-primitive-datatypes">W3C Schema, part 2, for the data type list. </a> </p>


<p>I've declared a number of variables, mostly as strings, which
contain other types, for example "6.0" as a string, which ensures it
can be converted to a decimal. The variable list is:</p>

<xsl:variable name="elAS"  as="element()">
  <p><em>Elements</em></p>
</xsl:variable>
<xsl:variable name="decAS" select="'3.1519'" as="xs:string"/>
<xsl:variable name="intAS" select="'2'" as="xs:string"/>
<xsl:variable name="boolAS" select="'true'" as="xs:string"/>
<xsl:variable name="bool2AS" select="'1'" as="xs:string"/>
<xsl:variable name="dateAS" select="'2003-06-16'" as="xs:string"/>
<xsl:variable name="ymdAS" select="'P1Y2M'" as="xs:string"/>

<xsl:variable name="dtdurAS" select="'P3DT10H30M'" as="xs:string"/>
<xsl:variable name="datetimeAS" select="'2003-06-19T08:18:05.2810Z'" as="xs:string"/>
<xsl:variable name="uriAS" select="'http://www.dpawson.co.uk/xsl'" as="xs:string"/>
<xsl:variable name="timeAS" select="'13:29:26.109Z'" as="xs:string"/>
<xsl:variable name="durAS" select="'P1Y2M3DT10H30M'" as="xs:string"/>
<xsl:variable name="qnameAS" select="'dp:element'" as="xs:string"/>
<xsl:variable name="base64AS" select="'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg=='" as="xs:string"/>
<xsl:variable name="strAS" select="' A string with lots
                                   of white space in it    '" as="xs:string"/>
<xsl:variable name="langAS" select="'en-UK'" as="xs:string"/>
<xsl:variable name="nameAS" select="'ident'" as="xs:string"/>
<xsl:variable name="itemAS" select="('ident', 'item', 'list3')" as="item()*"/>
<xsl:variable name="attset" as="attribute()+">
  <xsl:attribute name="x">attval1</xsl:attribute>
  <xsl:attribute name="y">attval2</xsl:attribute>
  <xsl:attribute name="z">attval3</xsl:attribute>    
</xsl:variable>


<pre>
&lt;xsl:variable name="elAS"  as="element()">
    &lt;p>&lt;em>Elements&lt;/em>&lt;/p>
&lt;/xsl:variable>
Gives  <xsl:copy-of select="$elAS"/>
&lt;xsl:variable name="decAS" select="'3.1519'" as="xs:string"/>
&lt;xsl:variable name="intAS" select="'2'" as="xs:string"/>
&lt;xsl:variable name="boolAS" select="'true'" as="xs:string"/>
&lt;xsl:variable name="bool2AS" select="'1'" as="xs:string"/>
&lt;xsl:variable name="dateAS" select="'2003-06-16'" as="xs:string"/>
&lt;xsl:variable name="ymdAS" select="'P1Y2M3'" as="xs:string"/>
&lt;xsl:variable name="dtdurAS" select="'P3DT10H30M'" as="xs:string"/>
&lt;xsl:variable name="datetimeAS" select="'2003-06-19T08:18:05.2810Z'" as="xs:string"/>
&lt;xsl:variable name="uriAS" select="'http://www.dpawson.co.uk/xsl'" as="xs:string"/>
&lt;xsl:variable name="timeAS" select="'13:29:26.109Z'" as="xs:string"/>
&lt;xsl:variable name="xAS" select="' '" as="xs:string"/>
&lt;xsl:variable name="durAS" select="'P1Y2M3DT10H30M'" as="xs:string"/>
&lt;xsl:variable name="qnameAS" select="'dp:element'" as="xs:string"/>
&lt;xsl:variable name="base64AS" select="'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg=='" as="xs:string"/>
&lt;xsl:variable name="strAS" select="' A string with lots
  of white space in it    '" as="xs:string"/>
&lt;xsl:variable name="langAS" select="'en-UK'" as="xs:string"/>
&lt;xsl:variable name="nameAS" select="'ident'" as="xs:string"/>
&lt;xsl:variable name="itemAS" select="('ident', 'item', 'list3')" as="item()*"/>
&lt;xsl:variable name="attset" as="attribute()+">
  &lt;xsl:attribute name="x">attval1&lt;/xsl:attribute>
  &lt;xsl:attribute name="y">attval2&lt;/xsl:attribute>
  &lt;xsl:attribute name="z">attval3&lt;/xsl:attribute>    
&lt;/xsl:variable>



</pre>
<p>Using the following value-of statements....</p>
<pre>
String => decimal - &lt;xsl:value-of select="xs:decimal($decAS)"/> 
String => float -   &lt;xsl:value-of select="xs:float($decAS)"/> 
String => double -   &lt;xsl:value-of select="xs:double($decAS)"/> 
String => integer -   &lt;xsl:value-of select="xs:integer($intAS)"/> 
String => duration -   &lt;xsl:value-of select="xs:duration($durAS)"/> 
String => yearMonthDuration -   &lt;xsl:value-of select="xdt:yearMonthDuration($ymdAS)"/> (note xdt ns) 
String => dayTimeDuration -   &lt;xsl:value-of select="xdt:dayTimeDuration($dtdurAS)"/> (note xdt ns) 
String => dateTime -   &lt;xsl:value-of select="xs:dateTime($datetimeAS)"/> 
String => date -   &lt;xsl:value-of select="xs:date($dateAS)"/> 
String => time -   &lt;xsl:value-of select="xs:time($timeAS)"/> 
String => anyURI -   &lt;xsl:value-of select="xs:anyURI($uriAS)"/> 
String => qname -   &lt;xsl:value-of select="xs:QName($qnameAS)"/> 
String => untyped () -   &lt;xsl:value-of select="xdt:untypedAtomic($qnameAS)"/> 
String => base64Binary -   &lt;xsl:value-of select="xs:base64Binary($base64AS)"/> 

String => boolean -  &lt;xsl:value-of select="xs:boolean($boolAS)"/>(input is true) 
String => boolean -  &lt;xsl:value-of select="xs:boolean($bool2AS)"/> (input is string 1) 
attribute =>String  - [&lt;xsl:value-of select="$attset[1]"/>]


item()*=> String - 
&lt;xsl:for-each select="$itemAS">
 Item  &lt;xsl:value-of select="position()"/> [&lt;xsl:value-of select="."/>]
&lt;/xsl:for-each>
Noting that item()* is the new lowest common denominator.
</pre>
<p> This gives: <br />
String => decimal - <xsl:value-of select="xs:decimal($decAS)"/> <br />
String => float -   <xsl:value-of select="xs:float($decAS)"/> <br />
String => double -   <xsl:value-of select="xs:double($decAS)"/> <br />
String => integer -   <xsl:value-of select="xs:integer($intAS)"/> <br />
String => duration -   <xsl:value-of select="xs:duration($durAS)"/> <br />
String => yearMonthDuration - <xsl:value-of select="xdt:yearMonthDuration($ymdAS)"/> (note xdt ns) <br />
String => dayTimeDuration -   <xsl:value-of select="xdt:dayTimeDuration($dtdurAS)"/> (note xdt ns) <br />  
String => dateTime -   <xsl:value-of select="xs:dateTime($datetimeAS)"/> <br />
String => date -   <xsl:value-of select="xs:date($dateAS)"/> <br />
String => time -   <xsl:value-of select="xs:time($timeAS)"/> <br />
String => anyURI -   <xsl:value-of select="xs:anyURI($uriAS)"/> <br />

String => untyped () -   <xsl:value-of select="xdt:untypedAtomic($qnameAS)"/> <br />
String => base64Binary -   &lt;xsl:value-of select="xs:base64Binary($base64AS)"/> Not in <xsl:value-of select="$saxonVsn"/> <br />


String => boolean -  <xsl:value-of select="xs:boolean($boolAS)"/>(input is true) <br />
String => boolean -  <xsl:value-of select="xs:boolean($bool2AS)"/> (input is string 1) <br />

 attribute =>String  - [<xsl:value-of select="$attset" separator=", "/>]<br />

item()*=> String - <br />
<xsl:for-each select="$itemAS">
 Item  <xsl:value-of select="position()"/> [<xsl:value-of select="."/>] <br />
</xsl:for-each>
Noting that item()* is the new lowest common denominator.

</p>



<h3 id="noAnd">Reduction in verbosity /  test on a sequence</h3>
<p>One of the additions that I find useful is the ability to test if
some piece of source document content is one from a,b,c,d. For instance, in 1.0
to test if an attribute value is a or b or c or d its necessary to write</p>
<pre>
   &lt;xsl:if test="@attVal = 'a' or @attval='b' ...... ">
</pre>
<p>With XSLT 2.0 its possible to write</p>
<pre>
    &lt;xsl:if test="@attVal = ('a','b','c','d')">
</pre>
<p>Note that this is usable in any test scenario, e.g. xsl:if, xsl:when etc.</p>



<h3 id="collation">Collation  <a href="http://www.w3.org/TR/xslt20/#collating-sequences">W3C </a></h3>

<p>This is novel.. for me. If you need a specific sort sequence, then this is helpful. As an example, I'm using a suite of input data as follows:

<pre>
&lt;?xml version="1.0" encoding="utf-8" ?>
&lt;doc>
 &lt;word>Hello&lt;/word>
 &lt;word>hello&lt;/word>
 &lt;word>[hello]&lt;/word>
&lt;word>Mword&lt;/word>
&lt;word>Nword&lt;/word>
&lt;word>Mother&lt;/word>
&lt;word>Nato&lt;/word>
&lt;word>:Mother&lt;/word>
&lt;word>5Mother&lt;/word>
&lt;word>&#x00FC;nter&lt;/word>
&lt;word>unter&lt;/word>
&lt;word>!unter&lt;/word>
&lt;word>$unter&lt;/word>

&lt;/doc>
</pre>
Of note is the Mword Nword pair. I want to sort these in reverse order, N before M.

The xslt is shown below.

<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema-datatypes" 
  xmlns:my="http://www.dpawson.co.uk/mylang"
  xmlns:saxon="http://saxon.sf.net/"
                version="2.0">

</pre>
Note the saxon namespace.

<pre>
&lt;saxon:collation
    class="mylang"
  <b> name="mylang" </b>
  default="yes"/>

</pre>


 Note the name attribute, referred to later, and the class attribute... a java collator; see below.
 The specification states that N comes before M

Then the actual sort:

<pre>
  &lt;xsl:template match="/">
    &lt;html>
      &lt;head>
        &lt;title>Collation&lt;/title>
        &lt;META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8" />
      &lt;/head>
      &lt;body>
        &lt;xsl:apply-templates/>
      &lt;/body>
    &lt;/html>
  &lt;/xsl:template>


  &lt;xsl:template match="doc">
    &lt;p>
      Before:  &lt;br />
 

  &lt;xsl:for-each select="word">
      &lt;xsl:value-of select="."/> &lt;br />
  &lt;/xsl:for-each>
&lt;/p>
&lt;hr />

  &lt;p>
    &lt;b>After&lt;/b> &lt;br />


  &lt;xsl:for-each select="word">
   &lt;xsl:sort select="."  
     data-type="text"
     lang="mylang"
  <b>    collation="mylang"/>  </b>
   &lt;xsl:value-of select="."/> &lt;br />
  &lt;/xsl:for-each>

&lt;/p>

  &lt;/xsl:template>
</pre>
The sort element refers back to the named collation, mylang.

Finally the java that does the sort.

<pre>
import java.text.Collator;
import java.text.RuleBasedCollator;
import java.text.ParseException;
import java.lang.StringBuffer;
import java.io.FileReader;
import java.io.BufferedReader;


import java.io.Serializable;
import net.sf.saxon.xpath.XPathException;
import net.sf.saxon.om.Item;
import java.io.File;

/**
 *Class mylang. Implements java.util.Comparator as a collator
 *
 *
 *
 *
 ***/
public class mylang implements java.util.Comparator,Serializable {

    public String ruleFileName="collator.txt";
    
    /**
     * Constructor 
     * Inits the rules from the given rules file.
     *
     **/
    public mylang (){
	String rules = getRules(ruleFileName);
    }

    /**
     * Compare two objects.
     * o1 &lt; o2  return -1
     * o1== o2  return 0
     * o1 > o2  return 1
     * @param o1 first object
     * @param o2 second object
     * @return int: -1 less than, 0 equal, +1 gt
     ***/
    public int compare (Object o1, Object o2) {
	int res= 0;
	String s1 ="";
	String s2 = "";
        try {
            s1 = (o1 instanceof String ? (String)o1 : ((Item)o1).getStringValue());
        } catch (XPathException err) {
            throw new ClassCastException("Cannot convert sort key from " + o1.getClass() + " to a string");
        }

   try {
            s2 = (o2 instanceof String ? (String)o2 : ((Item)o2).getStringValue());
        } catch (XPathException err) {
            throw new ClassCastException("Cannot convert sort key from " + o2.getClass() + " to a string");
        }

	RuleBasedCollator collator =  null;
	String rule = getRules(ruleFileName);

	try {
	    collator =  new RuleBasedCollator(rule);}
	catch (ParseException err) {
	    System.out.println("collator error: " +err.getMessage() + "Quitting" );
	    System.exit(2);
	}
	

	return collator.compare(s1,s2);
    }
    /**
     * Compares another collator with this one.
     * @param o1, the collator to be compared with this one.
     * @return boolean, always false. Not implemented.
     *
     **/
    public boolean equals (Object o1) {
	return false;

    }


    /**
     *Read a set of rules into a String
     *@param filename  name of the file containing the rules
     *@return String, the rules
     *
     **/
    private String getRules(String filename) {
	String res="";
	try{
	    BufferedReader reader = 
		new BufferedReader (new FileReader (filename));
	    StringBuffer buf=new StringBuffer();
	    String text;
	    try {
		while ((text=reader.readLine()) != null)
		    buf.append(text + "\n");
		reader.close();
	    }catch (java.io.IOException e) {
		System.err.println("Unable to read from rules file "+ filename);
		System.exit(2);
		
		}
	    res=buf.toString();


	}catch (java.io.FileNotFoundException e) {
	    System.out.println("Unable to read Rules file, quitting");
	    System.exit(2);
	}
	
	return res;
    }// end of getRules()


    /**
     *sort an array of strings according to the collator .
     *@param collator collator to use
     *@param words - words to sort
     *@return null.
     **/
   public static void sortStrings(Collator collator, String[] words) {
       String tmp;
       for (int i = 0; i &lt; words.length; i++) {
           for (int j = i + 1; j &lt; words.length; j++) {
               // Compare elements of the words array
               if( collator.compare(words[i], words[j] ) > 0 ) {
                   // Swap words[i] and words[j] 
                   tmp = words[i];
                   words[i] = words[j];
                   words[j] = tmp;
               }
           }
       }
   }
    /**
     *print an array of strings.
     *src: http://java.sun.com/docs/books/tutorial/i18n/text/rule.html
     *
     *
     **/
   public static void printStrings(String [] words) {
       for (int i = 0; i &lt; words.length; i++) {
          System.out.println(words[i]);
       }
   }
    /**
     *Default entry point for command line testing.
     *
     *
     *
     *
     **/
    public static void main (String [] argv) {
	RuleBasedCollator collator =  null;
	mylang mc = new mylang();
	String rule = mc.getRules(mc.ruleFileName);
	
	System.err.println(rule);
	try {
	    collator =  new RuleBasedCollator(rule);}
	catch (ParseException err) {
	    System.out.println("collator error: " +err.getMessage() );

	}
	String [] words = {
	    "Hello",
	    "hello",
	    ".hello",
	    " hello",
	    "&amp;hello",
	    "Back",
	    "back",
	    "Mother","Not", "4hello",
	    "!Hi",
	    "\u00FCnter",
	    "under",
	    "Under"
	};
	// print before sorting
	System.out.println("Initial Strings\n\t\t");
	mc.printStrings(words);
	mc.sortStrings(collator, words);
	System.out.println("\t\tPost sort");
	mc.printStrings(words);
    }

}
</pre>
You either follow this or not I guess. The actual rules are read in from a file, collator.txt,
at runtime. This file is as follows:

<pre>
  ' ' ,  ':' ,  ';' ,  '&lt;'  , '=' ,  '>'  , '?' ,  '@', '!',
 '[' ,  '\' ,  ']' ,  '^' ,  '_' ,  '`',
 '{' ,  '|' ,  '}' ,  '~'
 '!' ,  '"' ,  '#' ,  '$' ,  '%' ,  '&amp;',  ''' ,  '(' ,  ')' ,  '*'  , '+'  , ','  , '-' , '.' ,  '/'

&lt; A,a  &lt; B,b  &lt; C,c  &lt; D,d  &lt; E,e  &lt; F,f  &lt; G,g
&lt; H,h  &lt; I,i  &lt; J,j  &lt; K,k  &lt; L,l &lt; N,n   &lt; M,m 
&lt; O,o  &lt; P,p  &lt; Q,q  &lt; R,r  &lt; S,s  &lt; T,t
&lt; U,u &lt; &#x00FC;  &lt; V,v  &lt; W,w  &lt; X,x  &lt; Y,y  &lt; Z,z

&lt; 0  &lt; 1  &lt; 2  &lt; 3  &lt; 4  &lt; 5  &lt; 6  &lt; 7  &lt; 8  &lt; 9
</pre>

Note that N is specified to sort before M.

On running this the following output is generated:


</p>
      <p>
        <b> Before:</b>  <br/>Hello<br/>hello<br/>[hello]<br/>Mword<br/>Nword<br/>Mother<br/>Nato<br/>:Mother<br/>5Mother<br/>Ã¼nter<br/>unter<br/>!unter<br/>$unter<br/>
      </p>
      <hr/>
      <p>
         <b>After</b>
         <br/>:Mother<br/>Hello<br/>hello<br/>[hello]<br/>Nato<br/>Nword<br/>Mother<br/>Mword<br/>unter<br/>!unter<br/>$unter<br/>Ã¼nter<br/>5Mother<br/>
      </p>

      <p>Which has sorted, N before M, as required.</p>

      <p>Note: As of Aug 03, Saxon uses saxon:collation as follows.</p>
      <ul>
        <li>If class attribute is present, others are ignored.</li>
        <li>The rules attribute is not implemented. More later</li>

      </ul>


<h3 id="idiv">Integer Division <a href="http://www.w3.org/TR/xpath20/#prod-MultiplicativeExpr">W3C </a></h3>
      <p>Integer division. Produces an int from a pair of ints.
      <pre>
        &lt;xsl:variable name="i1" select="5" as="xs:integer"/>
        &lt;xsl:variable name="i2" select="2" as="xs:integer"/>
    a result of      &lt;xsl:value-of  select="$i1 idiv $i2"/>
      </pre>
5 idiv 2 gives 

        <xsl:variable name="i1" select="5" as="xs:integer"/>
        <xsl:variable name="i2" select="2" as="xs:integer"/>
      a result of  <xsl:value-of  select="$i1 idiv $i2"/>


</p>

      
<h3 id="regexGroup">Regex Groups <a href="http://www.w3.org/TR/xslt20/#element-analyze-string">w3c </a></h3>

<p>When using XSLT to mark up what is essentiall plain text, the grouping facility of the regexp facility
may be used, as in this example provided by David Carlisle.
</p>
<p>With an input file such as:
<pre>
&lt;doc>

&lt;r>Mateus 3.1-12; Lucas 3.1-20; &lt;/r>
&lt;r>words 1.2-12; Name 1.2-30&lt;/r>
&lt;r>LongString 1234.3-45; swd 1.2.1-2&lt;/r>
&lt;/doc>

</pre>
The following stylesheet fragment produces output as: 

<pre>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;wrap>


   &lt;canonRef Book="Mateus" chapter="3" verse="1" verseend="12" />
   &lt;canonRef Book="Lucas" chapter="3" verse="1" verseend="20" />

   &lt;canonRef Book="words" chapter="1" verse="2" verseend="12" />
   &lt;canonRef Book="Name" chapter="1" verse="2" verseend="30" />

   &lt;canonRef Book="LongString" chapter="1234" verse="3" verseend="45" />
&lt;/wrap>

</pre>
</p>
<pre>
  &lt;xsl:template match="doc">
    &lt;wrap>
    &lt;xsl:apply-templates/>
  &lt;/wrap>
  &lt;/xsl:template>
  
&lt;xsl:template match="r">
  &lt;xsl:analyze-string  regex="[^;]+" select=".">
    &lt;xsl:matching-substring>
      &lt;xsl:analyze-string  regex="([A-Za-z]+) *([0-9]+)\.([0-9]+)-([0-9]+)(.*$)" select=".">
        &lt;xsl:matching-substring>
          &lt;canonRef
  <b>         Book="{regex-group(1)}"
            chapter="{regex-group(2)}"
            verse="{regex-group(3)}"
            verseend="{regex-group(4)}"  </b>
            />
          &lt;/xsl:matching-substring>
        &lt;/xsl:analyze-string >
        &lt;/xsl:matching-substring>
      &lt;/xsl:analyze-string>
      
&lt;/xsl:template>


</pre>

<p>Note that each pattern in the regular expression, as defined by the braces, results in
a seperable attribute.</p>
<p>The final group (.*$) is there for debug purposes, catching the remainder of output
until the correct regexp strings are in place.</p>


<h3 id="unordered">Unordered function.  <a href="http://www.w3.org/TR/xquery-operators/#func-unordered">W3C</a> </h3>

<p>Weird one this. From the rec, <q>This function takes a sequence or more typically, an expression, that evaluates to a sequence, and indicates that the result sequence may be returned in any order.</q>

<br />
For example.

  <pre>
    &lt;xsl:variable name="ls" select="unordered(1 to 3)"/>
    &lt;xsl:for-each select ="$ls">
      &lt;xsl:value-of select="."/> &lt;xsl:text> &lt;/xsl:text>
    &lt;/xsl:for-each>
</pre>
Gives:
</p>

  <xsl:variable name="ls" select="unordered(1 to 3)"/>
    <xsl:for-each select ="$ls">
      <xsl:value-of select="."/> <xsl:text> </xsl:text>
    </xsl:for-each>
    <p>Which appears of little use to me</p>


    <h3 id="defPath">xpath-default-path <a href="http://www.w3.org/TR/xslt20/#unprefixed-qnames"
>W3C</a></h3>

    <p>Maybe due to confusion over namespaces, or just to save typing, when dealing with a 
namespaced document, whereas in 1.0, we had to write
    <pre>
      &lt;xsl:template match="ns:elementName" xmlns:ns="somethingOrOther">
</pre>
we can now write
<pre>
&lt;xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0"
   xpath-default-namespace="xyz">
</pre>

and the processor assumes all xpath expressions are in that namespace.
Neat!
</p>

<h3 id="data"> data() function <a href="http://www.w3.org/TR/xquery-operators/#func-data">W3C </a></h3>

<p> WD says,
<i>Summary: data() takes a sequence of items and returns a sequence
of atomic values.</i> It returns the typed value of the node passed as parameter.


For how it gets from one to the other see
the WD.

MK offered a use case; testing to see if this node a boolean?

<pre>
  &lt;xsl:if test="data(.) instance of xs:boolean">
    This node holds some data of type boolean.
  &lt;/xsl:if>

</pre>
<!--
On which basis I should be able to list out the 'atomic' values of,
say, all functions. Testing if the named functions return an integer type <br />

[<xsl:for-each select="//xsl:function">
Function <i><xsl:value-of select="@name "/></i>&#xA0;  <xsl:value-of select="if (data(.) instance of xs:string) then ' is an int' else 'is not an int'"/> <br /><xsl:text>,    </xsl:text>
</xsl:for-each>]
-->


</p>

<h3 id="deepeq">deep-equal(), <a href="http://www.w3.org/TR/xpath-functions#func-deep-equal">W3C </a></h3>


<p>Tests for equality. The spec defines this as (it is not straightforward) </p>

<blockquote>
they must either be atomic values that compare equal, or nodes of the
same kind, with the same name, whose children are deep-equal.
</blockquote>

<p>With two simple variables it shows as follows:

<pre>
&lt;xsl:variable name="de1" select="(1,2,3,4,5)" as="item()*"/>
&lt;xsl:variable name="de2" select="(1,2,3,4,5)" as="item()*"/>

&lt;xsl:value-of select="if (deep-equal($de1,$de2)) then 'equal' else 'not equal'"/>

<xsl:variable name="de1" select="(1,2,3,4,5)" as="item()*"/>
<xsl:variable name="de2" select="(1,2,3,4,5)" as="item()*"/>
Gives:  <xsl:value-of select="if (deep-equal($de1,$de2)) then 'equal' else 'not equal'"/>
</pre>
</p>


<h3 id="exactlyone">exactly-one(), <a href="http://www.w3.org/TR/xpath-functions#func-exactly-one">W3C </a></h3>

<p>An attempt to catch errors early. You judge if it succeeded.</p>

<xsl:variable name="singular" select="(1)" as="item()*"/>
<xsl:variable name="multiple" select="(1,2,3)" as="item()*"/>
<p>Note that this seems a little pointless. It does not inform
a user that a variable has more than one item or not. It raises
an error if the parameter has more than one item!  Hence I can write</p>
<pre>
&lt;xsl:variable name="singular" select="(1)" as="item()*"/>
&lt;xsl:variable name="multiple" select="(1,2,3)" as="item()*"/>

&lt;xsl:if test="exactly-one($singular)">
Singular has exactly one item.
&lt;/xsl:if>

yet I get an error with 

&lt;xsl:if test="exactly-one($multiple)">
Singular has exactly one item.
&lt;/xsl:if>
</pre>

<p>It seems to be a 'desperate measures' check on the typing system.
Note also <a href="http://www.w3.org/TR/xpath-functions/#func-one-or-more">one-or-more</a> and <a href="http://www.w3.org/TR/xpath-functions/#func-zero-or-one">zero-or-one()</a>, both similar in operation
</p>







<h3 id="tunnelling">Tunnelling, <a href="http://www.w3.org/TR/xslt20/#dt-tunnel-parameter">W3C </a></h3>

<p>The rule for named templates is exactly the same as for apply-templates: you only declare the parameter at the two ends of the tunnel: when the parameter is first created using xsl:with-param, and in a template that actually uses it with xsl:param.
</p>

<p>A tunnel parameter is created by using an xsl:with-param element that specifies tunnel="yes". A template that requires access to the value of a tunnel parameter must declare it using an xsl:param element that also specifies tunnel="yes".</p>

<h3 id="number">Number formatting    <a href="http://www.w3.org/TR/xslt20/#element-number">W3C></a></h3>

<p>The available forms of formatted numbers seems to have grown. Mike Kay posted an example to the list,

<pre>
&lt;xsl:variable name="val" select="1356" as="xs:integer"/>
&lt;xsl:number value="$val" format="w"/>
</pre>
Which produces, 

<xsl:variable name="val" select="1356" as="xs:integer"/>
<b><xsl:number value="$val" format="w"/></b> <br />
I.e. the number is converted to its word format!

</p>

<p>Or, given a sequence,
<pre>
&lt;xsl:variable name="seq" select="(1, 3, 5)" />
</pre>
The result of
<pre>
&lt;xsl:number value="$seq" format="A I w"/>
</pre>
<xsl:variable name="seq" select="(1, 3, 5)" />
is
<b><xsl:number value="$seq" format="A I w"/></b> <br />

</p>




<h3 id="remove">Remove an item from a sequence, <a href="http://www.w3.org/TR/xquery-operators/#func-remove">W3C</a></h3>

<p>remove($target, n ) as item()* is the description. From the target
remove the nth item. This struck me as useful for recursive templates,
where you want to process the cdr of the current node-set,
i.e. everything except the first element. In which case the use would
be

<pre>
  &lt;xsl:template name="recurse">
    &lt;xsl:param name="ns"/>    
... test for exit condition
... if more
    &lt;xsl:call-template name="recurse">
      &lt;xsl:with-param name="ns" select="remove($ns,1"/>
    &lt;/xsl:call-template>

  &lt;/xsl:template>
</pre>
Bit more elegant than 1.0?
 </p>


 <h3 id="mode">Addition to modes. Select all  modes  <a href="http://www.w3.org/TR/xslt20/#modes">W3C</a></h3>

 <p>Where you want to have something like &lt;xsl:template match="X" mode="*"/>,XSLT 2.0 now allows mode="#all"

</p>


<h3 id="sets">Except, Union and Intersection.</h3>

<p>Mike Kay offers this example of use. Given
<pre>
 $a= 1,2,3   
 $b= 2,3,5
 
 $a minus $b = 1
 $a differences to $b = 1,5
</pre>
except implements a mathematical set difference operation: $a except $b returns all nodes that are in $a excluding those that are also in $b. So it is asymmetric, as you observe.

If you want all the nodes that are in one set and not both you could do

<pre>($a union $b) except ($a intersection $b)</pre>

or

<pre>($a except $b) union ($b except $a)</pre>

</p>

<h3 id="docavail">doc-available(). <a href="http://www.w3.org/TR/xquery-operators/#func-namespace-uri">W3C</a> </h3>
<p>Returns true if a parsable entity is passed as a parameter</p>
<pre>
&lt;xsl:value-of select="if (doc-available('newfile.xml')) then
'File newfile.xml exists, and is XML' else 'File not found'"/>

gives

<xsl:value-of select="if (doc-available('newfile.xml')) then
'File newfile.xml exists, and is XML' else 'File not found'"/>

since the file exists.

</pre>



<h3 id="docs">Document() and doc(). <a href="http://www.w3.org/TR/xslt20/#function-document">W3C</a> and <a href="http://www.w3.org/TR/xpath-functions/#func-doc">W3C</a></h3>

<p>Document() is no different from the same function in XSLT 1.0</p>

<p>doc(), Retrieves a document using a URI supplied as an string. If
the URI is not valid an error is raised. If it is a relative URI
Reference, it is resolved relative to the value of the base URI
property from the context. I.e. its simpler. </p>


<h3 id="docuri">document-uri() <a href="http://www.w3.org/TR/xpath-functions#func-document-uri">W3C</a></h3>

<p>Returns the URI of the node passed as a parameter, e.g. for this document it is: 
<pre>
&lt;xsl:value-of select="document-uri(.)"/> gives <xsl:value-of select="document-uri(.)"/>
</pre>

</p>

<h3 id="prefixfromqname">prefix-from-QName() <a href="http://www.w3.org/TR/xpath-functions/#func-prefix-from-QName">W3C</a></h3>

<p>Provides the associated prefix given a namespace. E.g. <pre>
&lt;xsl:value-of select="prefix-from-QName(node-name(/d:doc))"/> gives <b>
<xsl:value-of select="prefix-from-QName(node-name(//d:doc))"/></b>
</pre>
which is clearly correct!
</p>


<h3 id="qname">QName() <a href="http://www.w3.org/TR/xpath-functions/#func-QName">W3C</a></h3>

<p>Provides the qualified name from the given parameter.
E.g.<pre> &lt;xsl:value-of select="QName('http://www.dpawson.co.uk/ns#','dp:doc')"/> gives <b><xsl:value-of select="QName('http://www.dpawson.co.uk/ns#','dp:doc')"/></b>
</pre>
As to a purpose for this... type conversion I guess.
</p>




<h3 id="inscopepref">in-scope-prefixes() <a href="http://www.w3.org/TR/xpath-functions#func-in-scope-prefixes">W3C</a></h3>

<p>Just as it says on the tin? E.g. for the stylesheet root this gives <b><xsl:value-of select="in-scope-prefixes(/xsl:stylesheet)"/></b> for 
<pre>
&lt;xsl:value-of select="in-scope-prefixes(/xsl:stylesheet)"/>
</pre>
</p>





<h3 id="lang">lang() <a href="http://www.w3.org/TR/xpath-functions#func-lang">W3C</a></h3>

<p>Boolean, checking if the language of the node specified matches that of the first param. E.g.
I've set the language of this stylesheet to en-UK, of which en is a subset. Hence
<pre>
&lt;xsl:value-of select="if (lang('en',/xsl:stylesheet)) then 'English' else 'not English'"/> gives: 
<b><xsl:value-of select="if (lang('en',/xsl:stylesheet)) then 'English' else 'not English'"/></b>
</pre>
</p>



<h3 id="number">number() <a href="http://www.w3.org/TR/xpath-functions/#func-number">W3C</a></h3>

<p>Convert the argument to a number... if possible</p>
<p>E.g. xsl:value-of select="number('3.151492')"/> gives <xsl:value-of
select="n