[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

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


Subject: RE: [xsl] Displaying a data grid - grouping and using current (not first occurrence) node
From: <Jarno.Elovirta@xxxxxxxxx>
Date: Wed, 21 Jul 2004 11:08:13 +0300

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 documentbunless 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


Current Thread