Subject: [xsl] Discrepancy in handling current() in a pattern From: Alain <alainb06@xxxxxxx> Date: Wed, 10 Jun 2009 21:32:03 +0200 |
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[@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[@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[@x != '1' and @z != ../cell[@y = current()/@y][@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[@y!='1' and @z != ../cell[@y = current()/@y -1][@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.
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Sort by one attribute & u, Michael Kay | Thread | Re: [xsl] Discrepancy in handling c, G. Ken Holman |
Re: [xsl] Sort by one attribute & u, James A. Robinson | Date | [xsl] A smarter choose operation XS, Karl Stubsjoen |
Month |