Hi,
I regularly find myself having to transform tables in XHTML. The data is
frequently organized by column headings. This seems like an obvious opportunity
for grouping using Keys, and I've gotten it to work, but I'm having trouble
understanding *why* it's working.
Please note that this is not the typical grouping example where an attribute or
element name identifies what group something belongs to but rather an example
in which an elements *position* relative to other elements is what defines the
group.
Given:
<table>
<tr>
<td>Fruits</td>
<td>Veggies</td>
<td>Lactose</td>
</tr>
<tr>
<td>Apples</td>
<td>Carrots</td>
<td>Milk</td>
</tr>
<tr>
<td>Bananas</td>
<td>Peas</td>
<td>Cheese</td>
</tr>
<tr>
<td>Plums</td>
<td>Celery</td>
<td>Eggs</td>
</tr>
</table>
I want to end up with:
<foods>
<foodGroup name="Fruits">
<food>Apples</food>
<food>Bananas</food>
<food>Plums</food>
</foodGroup>
<foodGroup name="Veggies">
<food>Carrots</food>
<food>Peas</food>
<food>Celery</food>
</foodGroup>
<foodGroup name="Lactose">
<food>Milk</food>
<food>Cheese</food>
<food>Eggs</food>
</foodGroup>
</foods>
I've found that the following XSLT works, but I don't understand why and I
suspect that I am just getting lucky or that the Key element could be better
written (optimized?).
I would be very grateful if someone with more experience at this than I could
take a look at this XSLT and explain:
1) How is a TD element (found in the USE attribute of my Key) able to act as
unique identifier for a TR element (it's parent)?
2) How should this be done (assuming mine is not optimal)?
Please note that I realize this does not require using keys (I don't think) but
I like using keys because it makes sense semantically.
Here's the XSLT and thanks in advance.
<xsl:key name="food-group" match="//table/tr[position() > 1]"
use="ancestor-or-self::table/tr[position() = 1]/td" />
<xsl:template match="/table">
<xsl:element name="foods">
<xsl:apply-templates select="tr[position() = 1]/td"/>
</xsl:element>
</xsl:template>
<xsl:template match="td">
<xsl:variable name="i" select="position()" />
<xsl:element name="foodGroup">
<xsl:attribute name="name"><xsl:value-of select="."
/></xsl:attribute>
<xsl:for-each select="key('food-group', .)">
<xsl:element name="food">
<xsl:value-of select="td[position() = $i]" />
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
Ted Stresen-Reuter
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--