RE: [xsl] for-each-group usage

Subject: RE: [xsl] for-each-group usage
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Wed, 7 Mar 2007 15:34:28 -0000
saxon:evaluate() is always going to be expensive. In situations where you
are using the same expression repeatedly (e.g. to calculate a sort key or a
grouping key) it's well worth splitting it into its two halves,
saxon:expression and saxon:eval:

<xsl:variable name="sortkey"
select="saxon:expression(../data-set/order-by/@xpath)"/>

then

<xsl:sort select="saxon:eval($sortkey)"/>

Michael Kay
http://www.saxonica.com/

 

> -----Original Message-----
> From: Angela Williams [mailto:Angela.Williams@xxxxxxxxxxxxxxxxxx] 
> Sent: 07 March 2007 15:19
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: RE: [xsl] for-each-group usage
> 
> That was it - thanks!
> 
> Is this stylesheet efficient or is there a better way of doing this?
> 
> -----Original Message-----
> From: Michael Kay [mailto:mike@xxxxxxxxxxxx]
> Sent: Tuesday, March 06, 2007 5:47 PM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: RE: [xsl] for-each-group usage
> 
> The group-by and order-by expressions both need to be 
> relative to the nodes being grouped. That is, you want the 
> group-by expression to be "d"
> rather
> than "doc('one.xml')/a/b/d" You seem to have fixed this for 
> the sort key (by using substring-after), but not for the grouping key.
> 
> Michael Kay
> http://www.saxonica.com/
> 
> 
> > -----Original Message-----
> > From: Angela Williams [mailto:Angela.Williams@xxxxxxxxxxxxxxxxxx]
> > Sent: 06 March 2007 22:33
> > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Subject: [xsl] for-each-group usage
> > 
> > Hello!
> > 
> > I have a mistake in my XSLT 2.0 stylesheet below that is 
> causing the 
> > grouping mechanism to not work properly. I've used for-each-group 
> > successfully in the past, but this is more complicated (or 
> I am just 
> > making it more so).
> > 
> > Will someone please point out my error?
> > Also, is there a more elegant/efficient way of going about this?
> > 
> > I have two xml files. One.xml contains my data objects and two.xml 
> > defines a list of table columns and tells me which data to put in 
> > which column. I need to match on my table columns and 
> inject the data 
> > at run time.
> > 
> > Desired output:
> > Seed Pod
> > Apple		E 
> > Orange	E
> > 
> > Root
> > Potato	E
> > Carrot	E
> > 
> > Actual output:
> > Seed Pod
> > Apple		E
> > Potato	E
> > Orange	E
> > Carrot	E
> > 
> > Root
> > Apple		E
> > Potato	E
> > Orange	E
> > Carrot	E
> > 
> > One.xml:
> > <a>
> >   <b>
> >     <c>Apple</c>
> >     <d>Seed Pod</d>
> >     <e> E </e>
> >   </b>
> >   <b>
> >     <c>Potato</c>
> >     <d>Root</d>
> >     <e> E </e>
> >   </b>
> >   <b>
> >     <c>Orange</c>
> >     <d>Seed Pod</d>
> >     <e> E </e>
> >   </b>
> >   <b>
> >     <c>Carrot</c>
> >     <d>Root</d>
> >     <e> E </e>
> >   </b>
> > </a>
> > 
> > Two.xml:
> > <table>
> >   <data-set>  
> >     <row-set xpath="doc('one.xml')/a/b"/>
> >     <group-by xpath="doc('one.xml')/a/b/d"/>
> >     <order-by xpath="doc('one.xml')/a/b/c"/>
> >   </data-set>
> >   <columns>
> >     <column>
> >       <data-value xpath="doc('one.xml')/a/b/c"/>
> >     </column>
> >     <column>
> >       <data-value xpath="doc('one.xml')/a/b/e"/>
> >     </column>
> >   </columns>
> > </table>
> > 
> > And my stylesheet (included in a master file - I can send that if
> > needed.):
> > <xsl:stylesheet xmlns:fo="http://www.w3.org/1999/XSL/Format"; 
> >   xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
> >   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; 
> >   xmlns:sax="http://saxon.sf.net/"; version="2.0">
> > 
> >   <xsl:template match="columns">
> >     <xsl:variable name="cols" select="." />
> > 
> >     <xsl:variable name="rows" as="xs:string">
> >       <xsl:value-of select="../data-set/row-set/@xpath" />
> >     </xsl:variable>
> > 
> >     <xsl:variable name="group" as="xs:string">
> >       <xsl:value-of select="../data-set/group-by/@xpath" />
> >     </xsl:variable>
> > 
> >     <xsl:variable name="sort" as="xs:string">
> >       <xsl:value-of select="../data-set/order-by/@xpath" />
> >     </xsl:variable>
> > 
> >     <xsl:for-each-group select="sax:evaluate($rows)" 
> >                         group-by="sax:evaluate($group)">
> >       <xsl:sort select="sax:evaluate(
> >                           substring-after($sort, concat($rows, '/'))
> >                         )" />
> >       <fo:table-row>
> >         <fo:table-cell>
> >           <fo:block>
> >             <xsl:value-of select="current-grouping-key()" />
> >           </fo:block>
> >         </fo:table-cell>
> >       </fo:table-row>
> >       <xsl:for-each select="current-group()">
> >         <xsl:variable name="node" select="." />
> >         <fo:table-row>
> >           <xsl:for-each select="$cols/column">
> >             <fo:table-cell column-number="{position()}">
> >               <fo:block>
> >                 <xsl:variable name="field">
> >                   <xsl:value-of select="data-value/@xpath" />
> >                 </xsl:variable>
> >                 
> >                 <xsl:value-of 
> >                    select="$node/sax:evaluate(
> >                              substring-after($field, concat($rows, 
> > '/'))
> >                           )" />
> >               </fo:block>
> >             </fo:table-cell>
> >           </xsl:for-each>
> >         </fo:table-row>
> >       </xsl:for-each>
> >     </xsl:for-each-group>
> >   </xsl:template>
> > </xsl:stylesheet>
> > 
> > Thanks!
> > Angela Williams
> > Angela.Williams@xxxxxxxxxxxxxxxxxx
> > Austin, TX

Current Thread