[xsl] for-each-group usage

Subject: [xsl] for-each-group usage
From: "Angela Williams" <Angela.Williams@xxxxxxxxxxxxxxxxxx>
Date: Tue, 6 Mar 2007 16:33:10 -0600
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