xsl-list
[Top] [All Lists]

RE: Displaying a data grid - grouping and using current (not first occurrence) node

2004-07-21 01:08:13
Hi,

My problem is that when loopoing over the unique keys, the 
node returned is
always the first node matching the key, which makes sense, 
but I need to
return the current node in order to get the correct value 
into the grid.
I'm looking for something like:

 ID        X    Y    A    B
r0001      123            456
r0002      1    789
r0003      45   3    2
r0004      67   89

Columns A and B should be reversed, as B appears before A in the example 
document—unless you want a second sort key which sorts the columns in reverse 
document order. Anyhow, e.g.

  <xsl:template match="records">
    <html>
      <body>
        <table border="1">
          <thead>
            <tr>
              <th>ID</th>
              <xsl:for-each select="record/test[generate-id(.) = 
generate-id(key('test-by-name', name))]">
                <xsl:sort select="count(key('test-by-name', name))" 
data-type="number" order="descending"/>
                <th>
                  <xsl:value-of select="name" />
                </th>
              </xsl:for-each>
            </tr>
          </thead>
          <tbody>
            <xsl:for-each select="record">
              <tr>
                <th>
                  <xsl:value-of select="id"/>
                </th>
                <xsl:variable name="current" select="."/>
                <xsl:for-each select="../record/test[generate-id(.) = 
generate-id(key('test-by-name', name))]">
                  <xsl:sort select="count(key('test-by-name', name))" 
data-type="number" order="descending"/>
                  <td>
                    <xsl:for-each select="$current/test[name = current()/name]">
                      <xsl:value-of select="value"/>
                    </xsl:for-each>
                  </td>
                </xsl:for-each>
              </tr>
            </xsl:for-each>
          </tbody>
        </table>
      </body>
    </html>
  </xsl:template>

If performance becomes a problem, write the column order into a variable as a 
space separated name list, then go through that list with a recursive template 
and output the cell values based on that

  <xsl:template match="records">
    <html>
      <body>
        <table border="1">
          <xsl:variable name="columns">
            <xsl:for-each select="record/test[generate-id(.) = 
generate-id(key('test-by-name', name))]">
              <xsl:sort select="count(key('test-by-name', name))" 
data-type="number" order="descending"/>
              <xsl:value-of select="name" />
              <xsl:text> </xsl:text>
            </xsl:for-each>
          </xsl:variable>
          <thead>
            <tr>
              <th>ID</th>
              <xsl:call-template name="header">
                <xsl:with-param name="columns" select="$columns"/>
                <xsl:with-param name="header" select="true()"/>
              </xsl:call-template>
            </tr>
          </thead>
          <tbody>
            <xsl:for-each select="record">
              <tr>
                <th>
                  <xsl:value-of select="id"/>
                </th>
                <xsl:call-template name="header">
                  <xsl:with-param name="columns" select="$columns"/>
                </xsl:call-template>
              </tr>
            </xsl:for-each>
          </tbody>
        </table>
      </body>
    </html>
  </xsl:template>
  <xsl:template name="header">
    <xsl:param name="columns" select="''"/>
    <xsl:param name="header" select="false()"/>
    <xsl:if test="$columns">
      <xsl:choose>
        <xsl:when test="$header">
          <th>
            <xsl:value-of select="substring-before($columns, ' ')"/>
          </th>
        </xsl:when>
        <xsl:otherwise>
          <td>
            <xsl:value-of select="test[name = substring-before($columns, ' 
')]/value"/>
          </td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:call-template name="header">
        <xsl:with-param name="columns" select="substring-after($columns, ' ')"/>
        <xsl:with-param name="header" select="$header"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

Cheers,

Jarno
<Prev in Thread] Current Thread [Next in Thread>