Re: [xsl] fill in a table with dynamic header at correct place

Subject: Re: [xsl] fill in a table with dynamic header at correct place
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Wed, 18 Jul 2001 10:42:00 +0100
Hi Jan,

> First: How can I get the -name- of each attribute which exists in an
> xml file (I need the name and not the value, because I have to build
> the header of a table by the attribute names, which are changing
> from xml file to xml file!!)

You can get the name of any node, as it appears in the source XML with
the name() function. Or you can get the local name of a node (without
a namespace prefix) using the local-name() function. For most
attributes these will give exactly the same thing.

You can find all the attributes in a document with the XPath:

  //@*

So to get the names of the attributes in a document, you can use
something like:

  <xsl:for-each select="//@*">
    <xsl:value-of select="name()" /><br />
  </xsl:for-each>

> I have a big problem to fill in dynamic tables. Header and number of
> cols are always different. I read the header of the table out of
> /SPStruct/definitions/col/@name !
> I want to put all stuff of ../data/row/col at the right place in the
> table, but this is the problem: if one attribute is empty, it does
> not appear in the xml file so I am not able to simply write the data
> in a row. I hope my explanation was not toooo bad and I hope
> somebody could HELP ME.

You need to use the column definitions to drive the output of the
rows. If you knew what column you were on (the relevant
definitions/col element stored in the $column variable) and you knew
what row you were on (the relevant row stored in the $row variable),
then you could work out the data to display by finding the col element
child of the $row whose name attribute was equal to the name attribute
of the $column:

  <xsl:variable name="data"
                select="$row/col[@name = $column/@name]" />

If there was such a col, you could output its value in a cell,
otherwise use a dummy value:

  <xsl:choose>
    <xsl:when test="$data">
      <td><xsl:value-of select="$data" /></td>
    </xsl:when>
    <xsl:otherwise>
      <td> sfidsgöisdg </td>
    </xsl:otherwise>
  </xsl:choose>

You can do this in a template that matches the definitions/col
elements in 'body' mode that accepts a parameter specifying the row:

<xsl:template match="definitions/col" mode="body">
  <xsl:param name="row" />
  <xsl:variable name="data"
                select="$row/col[@name = $column/@name]" />
  <xsl:choose>
    <xsl:when test="$data">
      <td><xsl:value-of select="$data" /></td>
    </xsl:when>
    <xsl:otherwise>
      <td> sfidsgöisdg </td>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

You can apply templates to the definitions/col elements in turn from
within the template that matches the row elements, and pass the row
element that you're on as the value of the $row parameter:

<xsl:template match="row">
  <tr>
    <xsl:apply-templates select="/SPStruct/definitions/col"
                         mode="data">
      <xsl:with-param name="row" select="." />
    </xsl:apply-templates>
  </tr>
</xsl:template>

That way the order in which the row/col elements are accessed is the
same as the order in which the definitions/col elements are given (and
thus in the same order as the headers).

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread