Please critique my solution: rendering HTML table using sparse data

S

Sandros

Background: I'm collecting usability statistics for a group of
applications. Each count has the following attributes: date,
application, major heading, minor heading, count. My intent is
to pull this back as XML and render it in to an HTML table.

I have all this working and all the files are below. I would
value any feedback.

A simple example of the data looks like this:

<counts-report>
<counts date="2004-10-07">
<application name="App A">
<major name="Major A">
<minor name="Minor A">1</minor>
<minor name="Minor C">7</minor>
</major>
</application>
</counts>
<counts date="2004-10-08">
<application name="App A">
<major name="Major A">
<minor name="Minor A">1</minor>
<minor name="Minor B">3</minor>
</major>
<major name="Major B">
<minor name="Minor A">15</minor>
</major>
</application>
</counts>
</counts-report>

The output I am looking for is something like:

+------------+---------------------------------------+
| | App A |
| +---------------------------------------+
| | Major A | Major B |
| +---------+---------+---------+---------+
| | Minor A | Minor B | Minor C | Minor A |
+------------+---------+---------+---------+---------+
| 2004-10-07 | 1 | | | |
+------------+---------+---------+---------+---------+
| 2004-10-07 | 1 | 3 | 7 | 15 |
+------------+---------+---------+---------+---------+
| Totals | 2 | 3 | 7 | 15 |
+------------+---------+---------+---------+---------+



Now I looked around for solutions that would let me tabularize
truely sparese data but didn't have any luck and no elegant
solutions came to mind.

The only solution I could come up with was to somehow massage the
data beforehand. The two choices I explored were

1) Turning it in to a non-sparse data set
2) Put a "domain" entry in front listing the union of all

I went with #2 (mainly because for real world data #1 would
inflate the size of the file significantly). So the final file
looks like:


<counts-report>
<domain>
<application name="App A">
<major name="Major A">
<minor name="Minor A"/>
<minor name="Minor B"/>
<minor name="Minor C"/>
</major>
<major name="Major B>
<minor name="Minor A"/>
</major>
</application>
</domain>
<counts date="2004-10-07">
<application name="App A">
<major name="Major A">
<minor name="Minor A">1</minor>
<minor name="Minor C">7</minor>
</major>
</application>
</counts>
<counts date="2004-10-08">
<application name="App A">
<major name="Major A">
<minor name="Minor A">1</minor>
<minor name="Minor B">3</minor>
</major>
<major name="Major B">
<minor name="Minor A">15</minor>
</major>
</application>
</counts>
</counts-report>

The XSLT I am using is at the end of this message. This is my
first non-trivial XSLT experiment so I would appreciate any
comments. A couple of specific questions:

1) I wanted to put &nbsp; in blank cells instead of "-". I
couldn't get the parsers to accept the &nbsp; (verbatim) in
the xslt file (line 60)

2) I used two templates for minor and non-minor table headers
because the colpan value was comming out to zero when (@line
27 & 34... referenced at 11, 12, and 13).

3) I access the actual data for each row by constructing a
path expression using each "minor" entry found in the
domain (line 55).

I would also value any stylistic comments.

Thanks in advance for any help

Charlie


1: <?xml version="1.0" encoding="UTF-8"?>
2: <xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
3: <xsl:eek:utput method="html" version="1.0" encoding="UTF-8"
indent="yes"/>
4: <xsl:template match="/counts-report">
5: <html>
6: <head>
7: <title>My Table</title>
8: </head>
9: <body>
10: <table border="1" cellpadding="5">
11: <tr> <th rowspan="3">Date</th> <xsl:apply-templates
mode="header" select="domain/application"/> </tr>
12: <tr> <xsl:apply-templates mode="header"
select="domain/application/major"/> </tr>
13: <tr> <xsl:apply-templates mode="header"
select="domain/application/major/minor"/> </tr>
14:
15: <xsl:apply-templates mode="data" select="counts"/>
16:
17: <tr>
18: <th> Totals </th>
19: <xsl:apply-templates mode="totals"
select="domain/application/major/minor"/>
20: </tr>
21:
22: </table>
23: </body>
24: </html>
25: </xsl:template>
26:
27: <xsl:template mode="header" match="*">
28: <xsl:element name="th">
29: <xsl:attribute name="colspan"><xsl:value-of
select="count(.//minor)"/></xsl:attribute>
30: <xsl:value-of select="@name"/>
31: </xsl:element>
32: </xsl:template>
33:
34: <xsl:template mode="header" match="minor">
35: <xsl:element name="th">
36: <xsl:value-of select="@name"/>
37: </xsl:element>
38: </xsl:template>
39:
40: <xsl:template mode="data" match="counts">
41: <xsl:variable name="rownum" select="position()"/>
42:
43: <xsl:element name="tr">
44: <xsl:if test="$rownum mod 2 = 0">
45: <xsl:attribute name="style">background-color: rgb(0, 204,
204);</xsl:attribute>
46: </xsl:if>
47:
48: <th> <xsl:value-of select="@date"/> </th>
49:
50: <xsl:for-each
select="/counts-report/domain/application/major/minor">
51: <xsl:variable name="app" select="../../@name"/>
52: <xsl:variable name="major" select="../@name"/>
53: <xsl:variable name="minor" select="@name"/>
54:
55: <xsl:variable name="value"
select="/counts-report/counts[$rownum]/application[@name=$app]/major[@name=$major]/minor[@name=$minor]"/>
56:
57: <td>
58: <xsl:choose>
59: <xsl:when test="$value"> <xsl:value-of
select="$value"/> </xsl:when>
60: <xsl:eek:therwise> - </xsl:eek:therwise>
61: </xsl:choose>
62: </td>
63:
64: </xsl:for-each>
65:
66: </xsl:element>
67:
68: </xsl:template>
69:
70: <xsl:template mode="totals" match="minor">
71: <xsl:param name="app" select="../../@name"/>
72: <xsl:param name="major" select="../@name"/>
73: <xsl:param name="minor" select="@name"/>
74:
75: <td>
76: <xsl:value-of
select="sum(/counts-report/counts/application[@name=$app]/major[@name=$major]/minor[@name=$minor])"/>
77: </td>
78: </xsl:template>
79:
80: </xsl:stylesheet>
 
D

David Carlisle

1) I wanted to put &nbsp; in blank cells instead of "-". I
couldn't get the parsers to accept the &nbsp; (verbatim) in
the xslt file (line 60)

This is the most FFF FAQ on xsl-list (which maintains a faq at
www.dpawson.co.uk)

XML only predefines 5 entities (amp quot apos lt gt) so if you want to
use any other you need to redefine them in a DD and reference that DTD
in a doc type. In this case you don't need an entity at all you just
want to but a no break space into the result tree which is character 160
so
& # 1 6 0 ;
(without the spaces) if outputting html this will probably come out as
the entity nbsp but it may come out as character data (depending on your
processor) either way it will work in a browser.


You don't need to use xsl:element unless you are generating element
names dynamically so

<xsl:element name="th">
36: <xsl:value-of select="@name"/>
37: </xsl:element>

could more easily be written

<th>
36: <xsl:value-of select="@name"/>
37: </th>

almost certainly makes no difference to the processing speed or anything
else though, just easier to read.

David
 
J

John Fereira

(e-mail address removed) (Sandros) wrote in

1) I wanted to put &nbsp; in blank cells instead of "-". I
couldn't get the parsers to accept the &nbsp; (verbatim) in
the xslt file (line 60)

Replace &nbsp; with  

There are a couple of other solutions I prefer to use:

Create a transparent.gif image that is 1 pixel wide and 1 pixel high.

Whenever you need white space use it in an img tag with scaled height width
values:

<img src="transparent.gif" width="10" height="5" alt=" " border="0" />

Alternatively, use can use css styles:

<td style="background-image: url(transparent.gif); background-repeat:repeat-
x;" width="20"></td>
 
G

GIMME

Regarding style.

It's my opinion that xhtml should look as much as possible as html
and that the number of templates should be kept to a minimum.

Some of what you do as a template I'd recommend doing "in line".

That way if you can turn the project over to an html person.

It reads easier too. (Lines 11-14 look messy.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top