XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition (735 page)

BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition
9.33Mb size Format: txt, pdf, ePub

Now we can move on to the initial template. In XSLT 2.0 I can define the initial template as a named template, so that it can be invoked directly from the command line, without specifying a source document. However, just in case you're using a processor that doesn't support this capability, it does no harm to define the template with
match=“/”
as well.

The root template defines the stages of processing, as follows:

1.
Validate the supplied parameter.

2.
Set up the empty board and place the knight on it at the specified starting square.

3.
Compute the knight's tour.

4.
Print out the tour in HTML format.

These tasks are all delegated to stylesheet functions or templates, so the root template itself is quite simple:


    

    

    
[a-h][1-8]$’))”>

        

                     select=“Invalid start parameter: try say ‘a1’ or ‘g6’”/>

    

    

    

         select=“for $i in (1 to 64) return 0”/>

    

    

         select=“tour:place-knight(1, $empty-board,

                                      $start-row * 8 + $start-column)”/>

    

    

        select=“tour:make-moves(2, $initial-board,

                                    $start-row * 8 + $start-column)”/>

    

    

        

    


Notice the style of coding here, which uses a sequence of variables, each one computed from the value of the previous variable. Each variable is used only once, which means the variables aren't actually necessary: it would be possible to nest all the function calls inside each other, and express the whole calculation using one big XPath expression inside the call to the final
print-board
template. But in my view, writing the processing logic like this as a sequence of steps makes it much easier to explain what's going on. The
as
clauses, which define the type of each variable, also provide useful documentation. (I also found that while I was writing this code, the type checking provided by the
as
clauses caught many of my errors.)

The code for validating the
start
parameter uses a simple regular expression. The symbols

and
$
match the start and end of the input string, and the body of the regular expression specifies that the string must consist of a single letter in the range [a–h] followed by a single digit in the range [1–8]. If the parameter doesn't match, the stylesheet outputs a message using

and terminates.

Several of the variables (
empty-board
,
initial-board
, and
final-board
) represent a chessboard containing all or part of a knight's tour. Each of these variables is a sequence of 64 integers in the range 0 to 64. If the square has been visited, it contains a sequence number representing the order of visiting (1 for the start square, 2 for the next square visited, and so on). If the square has not been visited, the value is zero. The type
as=“xs:integer*”
is actually much more liberal that this: it doesn't constrain the sequence to be of length 64, and it doesn't constrain the range of values to be 0 to 64. We could define a schema with a user-defined atomic type that allows only integers in the range 0 to 64, but it would seem overkill to import a schema just for this purpose, quite apart from the fact that the stylesheet would then work only with a schema-aware XSLT processor. Even then, restricting the size of the sequence to 64 is not something that the type system can achieve. Although list types can be defined in XML Schema to have a fixed length, this constraint can only be exploited in XSLT when validating an element or attribute node against this list type. Freestanding sequences of atomic values, like the ones being used here, cannot refer to a list type defined in the schema.

Other books

Good People by Robert Lopez
Your Body is Changing by Jack Pendarvis
Like Fire Through Bone by E. E. Ottoman
The Black Cauldron by Alexander, Lloyd
Wonder Guy by Stone, Naomi