The first can be solved by using the more exact XPath:
<xsl:variable name="unique-rows" select="/page/include/tables/table/row/[EMAIL PROTECTED]'ID'][not(.=preceding::[EMAIL PROTECTED]'ID'])]"/>
The second one at least partly by switching to preceding-sibling:
<xsl:variable name="unique-rows" select="/page/include/tables/table/row[not([EMAIL PROTECTED]'ID'] = preceding-sibling::[EMAIL PROTECTED]'ID'])]/[EMAIL PROTECTED]'ID']"/>
But there are still a few problems: don't use global variables if not necessary. In your sample you can simply move the $unique-rows variable into the first template without changing anything else. (But maybe you only have shortened the stylesheet ...)
Then you are obfuscating the processing flow a bit in the stylesheet. If you or someone else later wants to maintain the stylesheet the uniqueness of the row processed at a template matching field makes it not easier. Also selecting key()[1] and key()[2] are a bit obfuscating. Show the real sense of them! You can change it like the following:
<xsl:variable name="unique-rows" select="/page/include/tables/table/row[not([EMAIL PROTECTED]'ID'] = preceding-sibling::[EMAIL PROTECTED]'ID'])]"/>
and later on the template:
<xsl:template match="row">
<xsl:variable name="val" select="[EMAIL PROTECTED]'ID']"/>
<row id="{position()}">
<field name="KEY"><xsl:value-of select="key('rows', $val)[EMAIL PROTECTED]'PARAM']='KEY']/[EMAIL PROTECTED]'VALUE']"/></field>
<field name="VALUE"><xsl:value-of select="key('rows', $val)[EMAIL PROTECTED]'PARAM']='VALUE']/[EMAIL PROTECTED]'VALUE']"/></field>
</row>
</xsl:template>
But as you can see the XPath for $unique-rows is still really long and more or less unreadable. A clever man named Steve Muench invented a grouping method, in the meantime called Muenchian Method (http://www.jenitennison.com/xslt/grouping/muenchian.html). One part of it you already have set up: the key declaration. The missing part is the selection of the unique rows:
<xsl:variable name="unique-rows" select="/page/include/tables/table/row
[count(. | key('rows', [EMAIL PROTECTED]'ID'])[1]) = 1]"/>There are at least 2 advantages: It's "standardized" in the sense of well-known. And the processing is optimized (XSLT processors can further optimize it as it is a standardized technique).
If you then add a further modularization ("templatization") for accessing KEY and VALUE you get the stylesheet I attached.
I hope it helps :-)
Joerg
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="name"/>
<xsl:key name="rows" match="row" use="[EMAIL PROTECTED]'ID']"/>
<xsl:key name="param-fields" match="[EMAIL PROTECTED]'VALUE']" use="concat(../[EMAIL PROTECTED]'ID'], '::', ../[EMAIL PROTECTED]'PARAM'])"/>
<xsl:template match="/">
<xsl:variable name="unique-rows" select="/page/include/tables/table/row
[count(. | key('rows', [EMAIL PROTECTED]'ID'])[1]) = 1]"/>
<table name="{$name}">
<xsl:apply-templates select="$unique-rows"/>
</table>
</xsl:template>
<xsl:template match="row">
<xsl:variable name="id" select="[EMAIL PROTECTED]'ID']"/>
<row id="{position()}">
<xsl:apply-templates select="key('param-fields', concat($id, '::KEY'))"/>
<xsl:apply-templates select="key('param-fields', concat($id, '::VALUE'))"/>
</row>
</xsl:template>
<xsl:template match="field">
<field name="{../[EMAIL PROTECTED]'PARAM']}">
<xsl:value-of select="."/>
</field>
</xsl:template>
</xsl:stylesheet>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
