Please critique my solution: rendering HTML table using sparse data

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Sandros

    Please critique my solution: rendering HTML table using sparse data

    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:styleshe et version="1.0"
    xmlns:xsl="http ://www.w3.org/1999/XSL/Transform">
    3: <xsl:output 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">Dat e</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:attribut e 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="positio n()"/>
    42:
    43: <xsl:element name="tr">
    44: <xsl:if test="$rownum mod 2 = 0">
    45: <xsl:attribut e name="style">ba ckground-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:otherwis e> - </xsl:otherwise>
    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>
  • David Carlisle

    #2
    Re: Please critique my solution: rendering HTML table using sparse data


    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

    Comment

    • John Fereira

      #3
      Re: Please critique my solution: rendering HTML table using sparse data

      cfineman@yahoo. com (Sandros) wrote in
      news:9c3eb1f0.0 411040842.3a4f7 7a2@posting.goo gle.com:

      [color=blue]
      >
      > 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)[/color]

      Replace &nbsp; with &#160;

      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="transparen t.gif" width="10" height="5" alt=" " border="0" />

      Alternatively, use can use css styles:

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

      Comment

      • GIMME

        #4
        Re: Please critique my solution: rendering HTML table using sparse data

        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.)

        Comment

        Working...