Hi experts,
here is what I am trying to do.
*"Business" requirements:*
-------------------------
I want to display a table (Sudoku-like) in a browser.
The values of the cells in the tables are stored in a XML file.
The browser receives directly the XML and has to display it nicely.
[Meaning I am limited to XSLT 1.0]
Every cell in the table as "coordinates" :
x, y, z
x: abcissa or column number (starts at 1, increment by 1)
y: ordinate or row number (starts at 1, increment by 1)
z: zone (as in Sudoku zones, eg a 3x3 square on an 9x9 Sudoku)
The table has to be displayed according to x, y -easy part!-
Lines has to be displayed, horizontally or vertically when there is a
change of zone
Typical Sudoku would then be
(I try some ASCII Art here, put your mail client in "fixed font")
1 2 3 | 4 5 6 | 7 8 9
2 3 1 | 5 6 4 | 9 7 8
3 1 2 | 6 4 5 | 8 9 7
=========+===========+==========
4 5 6 | 7 8 9 | 1 2 3
5 6 4 | 9 7 8 | 2 3 1
And so on.
So you have 4 types of cells:
- those who have a line on the left
- those who have a line on the top
- those who have both lines
- those who have no line at all
In the above figure, we have 6 "zones" separated by horizontal or
vertical lines.
*The XML*
-------
<?xml version="1.0" encoding="utf-8"?>
<sudoku>
<cell x="1" y="1" z="1"></cell>
<cell x="2" y="1" z="1"></cell>
<cell x="3" y="1" z="1">7</cell>
<cell x="4" y="1" z="2">2</cell>
<cell x="5" y="1" z="2"></cell>
<cell x="6" y="1" z="2"></cell>
<cell x="7" y="1" z="3"></cell>
<cell x="8" y="1" z="3"></cell>
<cell x="9" y="1" z="3"></cell>
<cell x="1" y="2" z="1"></cell>
<cell x="2" y="2" z="1"></cell>
<cell x="3" y="2" z="1"></cell>
<!-- and so on -->
</sudoku>
*The XSL*
-------
<?xml version='1.0' encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8"/>
<xsl:template match="/sudoku">
<!-- HTML blah-blah-->
<html>
<head>
<title>Displaying Sudoku</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="sudostyle.css"/>
</head>
<body bgcolor="#F9F9FF">
<p class="a">Puzzle</p>
<table cellspacing="0">
<!-- Here, we select first cell of each row and apply the row template-->
<xsl:apply-templates select="cell[(_at_)x = '1']" mode="row">
<xsl:sort select="@y" data-type="number"/>
</xsl:apply-templates>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="cell" mode="row">
<tr>
<xsl:apply-templates select="../cell[(_at_)y= current()/@y]" mode="cell">
<xsl:sort select="@x" data-type="number"/>
</xsl:apply-templates>
</tr>
</xsl:template>
<!-- First "stack" of matching for vertical lines -->
<!-- This matches cells that have a vertical lines on their left -->
<xsl:template match="cell[(_at_)x != '1' and @z != ../cell[(_at_)y =
current()/@y][(_at_)x= current()/@x - 1]/@z]" mode="cell" priority="2">
<xsl:apply-templates select="." mode="cell-2">
<xsl:with-param name="normal" select="'d'"/>
<xsl:with-param name="border" select="'f'"/>
</xsl:apply-templates>
</xsl:template>
<!-- And so, this matches other cells (those who do NOT have the
vertical line) -->
<xsl:template match="cell" mode="cell" priority="1">
<xsl:apply-templates select="." mode="cell-2">
<xsl:with-param name="normal" select="'c'"/>
<xsl:with-param name="border" select="'e'"/>
</xsl:apply-templates>
</xsl:template>
<!-- Second "stack" of matching for horizontal lines -->
<!-- This matches cells that have a horizontal lines on their top -->
<xsl:template match="cell[(_at_)y!='1' and @z != ../cell[(_at_)y = current()/@y
-1][(_at_)x= current()/@x]/@z]" mode="cell-2" priority="2">
<xsl:param name="border"/>
<td class="{$border}">
<xsl:apply-templates select="." mode="inner"/>
</td>
</xsl:template>
<!-- And so, this matches other cells (those who do NOT have the
horizontal line) -->
<xsl:template match="cell" mode="cell-2" priority="1">
<xsl:param name="normal"/>
<td class="{$normal}">
<xsl:apply-templates select="." mode="inner"/>
</td>
</xsl:template>
<!-- Here, we display the content of the cell -->
<xsl:template match="cell" mode="inner">
<p class="b"><xsl:value-of select="."/></p>
</xsl:template>
</xsl:stylesheet>
*Comments:*
--------
Of course, the 4 types of cells are just mapped to 4 different CSS
styles (class c,d,e,f).
Problems arose because I remembered the lesson and I tried to avoid the
ugly case/otherwise and made templates to sort out cells with borders.
Results:
--------
Firefox 3 : works fine
I.E. 6 or 7 : says that current() is not allowed in a pattern
Xalan : works fine (no error or warning)
Saxon 9 (runing as a XSLT1.0 stylesheet or as an XSLT2.0, makes no
difference) reports a recoverable error on the match. The error seems to
be that current() is of type untypedAtomic and node() type is expected.
As we are matching nodes, I assume the cast() works and it can be recovered.
So my questions:
---------------
1) Because of the discrepancy I noticed between Firefox and I.E, my
first question is: "Is current() allowed or not in an XSLT1.0 pattern?"
(or maybe it is "implementation defined or dependant" but XSLT1.0 is
unclear about that... or I couldn't find it!)
2) Is is allowed in XSLT2.0 -should be because Saxon do not complain
about current() itself, but about its type-, and what is the correct
expression to remove the recoverable error?
/Although I would probably try to code this puzzle differently in 2.0,
using for example a for-each-group/
3) Do you think of a better way to program this puzzle that should be
compatible with both I.E. and Firefox, apart from doing a unique pattern
with an ugly stack of 2 nested cases/otherwise.
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--