[xsl] New approach to grouping problem that doesn't use keys or axes

Subject: [xsl] New approach to grouping problem that doesn't use keys or axes
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Wed, 17 Oct 2001 08:52:29 -0400
At 01/10/16 16:40 -0400, Langdon, Jeffrey wrote:
I have an XML file that includes
a list of employees and their respective departments.  I need to loop
through the xml and sort the employees by department alphabetically.

You don't mention if you are using a processor that does or does not support the key() function, so I thought I would share something I figured out last month when I was in a position of being obliged to use a processor that does not.


An alternative available in some situations to using the full Muenchian method is a hybrid method using variables. This turned out to be *very* handy when grouping within subtrees, as using the Muenchian method for subtrees involves an elaborate key building approach as documented in:

http://www.biglist.com/lists/xsl-list/archives/200011/msg00757.html

One property variables share with key tables is that their members are in document order, thus at any time during the process (not just at the very start when building key tables), one can create a locally-scoped variable with only those nodes that need to be grouped. Then, as we learned from the Muenchian method, the use of the generated identifier for a node can determine the first node in document order for a given value.

Your problem is solved below using a locally-scoped variable to illustrate how this grouping can be done easily when in a subtree of a much larger source node tree.

I am not sure how to make the (Name) TreeNode element a child element of
the (Department) TreeNode element and then populate all the employees
within that department.
...
Here is the XML file -

<NewDataSet>
...
                        <cn>Belki Hercules</cn>
                        <Department>ITl</Department>
                        <Name>Belki Hercules</Name>

I'm assuming from the result that the above Department has a typo and should be "IT" not "IT1".


Please find below the hybrid grouping approach using variables that successfully runs with the XT processor that does not support the xsl:key instruction or key() function. I've successfully used this locally-scoped grouping approach a few times since then, and I've updated the upcoming 10th edition of my "Practical Transformation Using XSLT and XPath" book with this algorithm. I hope the 10th edition will be out soon, and it will of course be free to all customers who have purchased any earlier edition.

When I taught this last week in instructor-led training as one step *before* teaching the Muenchian method, the class seemed to catch on to the full Muenchian method much more quickly. Note that my approach does not deliver a node set the way the Muenchian method does, but not every grouping solution needs an intermediate node set. But for those that do, I still teach the Muenchian method as the next step in sophistication after teaching this local-variable approach.

And, when I was obliged to use XT, this approach solved my grouping problem much faster than using the source node tree axes. Oh, and in that case I ended up using a global variable instead of a local variable because my groups were scoped across the entire document, but that doesn't change the algorithm at all, just where the variable is declared.

I hope you find this useful.

......................... Ken

T:\jeff>type jeff.xml
<NewDataSet>
            <Table>
                        <cn>Acevedo, Antonia</cn>
                        <Department>Dispatch-Freight</Department>
                        <Name>Acevedo, Antonia</Name>
            </Table>
            <Table>
                        <cn>Aimone, Charlie</cn>
                        <Department>IT</Department>
                        <Name>Aimone, Charlie</Name>
            </Table>
            <Table>
                        <cn>Arenas, Lizalyn</cn>
                        <Department>Dispatch-Freight</Department>
                        <Name>Arenas, Lizalyn</Name>
            </Table>
            <Table>
                        <cn>Arrendell, Miguel</cn>
                        <Department>Warehouse</Department>
                        <Name>Arrendell, Miguel</Name>
            </Table>
            <Table>
                        <cn>Bayron, Jun</cn>
                        <Department>Warehouse</Department>
                        <Name>Bayron, Jun</Name>
            </Table>
            <Table>
                        <cn>Belki Hercules</cn>
                        <Department>IT</Department>
                        <Name>Belki Hercules</Name>
            </Table>
</NewDataSet>

T:\jeff>type jeff.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="1.0">

<xsl:output indent="yes"/>

<xsl:template match="/">
  <TREENODE>
    <xsl:apply-templates/>
  </TREENODE>
</xsl:template>

<xsl:template match="NewDataSet">
  <xsl:variable name="tables" select="Table"/>
  <xsl:for-each select="$tables">
    <xsl:sort select="Department"/>
    <xsl:variable name="dept" select="Department"/>
    <xsl:if test="generate-id(.)=
                  generate-id($tables[Department=$dept])">
      <!--found first of each department in document order-->
      <TreeNode Text="{$dept}">
        <xsl:for-each select="$tables[Department=$dept]">
          <TreeNode Text="{Name}"/>
        </xsl:for-each>
      </TreeNode>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

T:\jeff>xt jeff.xml jeff.xsl
<?xml version="1.0" encoding="utf-8"?>
<TREENODE>
<TreeNode Text="Dispatch-Freight">
<TreeNode Text="Acevedo, Antonia"/>
<TreeNode Text="Arenas, Lizalyn"/>
</TreeNode>
<TreeNode Text="IT">
<TreeNode Text="Aimone, Charlie"/>
<TreeNode Text="Belki Hercules"/>
</TreeNode>
<TreeNode Text="Warehouse">
<TreeNode Text="Arrendell, Miguel"/>
<TreeNode Text="Bayron, Jun"/>
</TreeNode>
</TREENODE>



--
G. Ken Holman                      mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Crane Softwrights Ltd.               http://www.CraneSoftwrights.com/s/
Box 266, Kars, Ontario CANADA K0A-2E0     +1(613)489-0999   (Fax:-0995)
Web site:     XSL/XML/DSSSL/SGML/OmniMark services, training, products.
Book:  Practical Transformation Using XSLT and XPath ISBN 1-894049-06-3
Article: What is XSLT? http://www.xml.com/pub/2000/08/holman/index.html
Next public training (instructor-live, Internet-live, and web-based):
-2001-10-22,11-01,11-02,11-05,11-19,11-21,12-03,12-05,12-09,12-10,12-19


XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread