cocoon-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Joerg Heinicke <joerg.heini...@gmx.de>
Subject Re: XSL question (was: XSL question in Cocoon)
Date Fri, 05 Dec 2003 07:08:00 GMT
After Josh's good analysis and solution for your problem I want to add 
some comments from the XSLT point of view. The solution is 
"sub-optimal", you have to bad axes in your expression: the descendant 
axis ('//') and the preceding axis. Both used in combination can slow 
down the processing extremely if you have a bigger data base to transform.

The first can be solved by using the more exact XPath:
<xsl:variable name="unique-rows" 
select="/page/include/tables/table/row/field[@name='ID'][not(.=preceding::field[@name='ID'])]"/>

The second one at least partly by switching to preceding-sibling:
<xsl:variable name="unique-rows" 
select="/page/include/tables/table/row[not(field[@name='ID'] = 
preceding-sibling::field[@name='ID'])]/field[@name='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(field[@name='ID'] = 
preceding-sibling::field[@name='ID'])]"/>

and later on the template:

<xsl:template match="row">
   <xsl:variable name="val" select="field[@name='ID']"/>
   <row id="{position()}">
     <field name="KEY"><xsl:value-of select="key('rows', 
$val)[field[@name='PARAM']='KEY']/field[@name='VALUE']"/></field>
     <field name="VALUE"><xsl:value-of select="key('rows', 
$val)[field[@name='PARAM']='VALUE']/field[@name='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', field[@name='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

Mime
View raw message