This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
New approach to grouping problem that doesn't use keys or axes
- To: XSL List <xsl-list at lists dot mulberrytech dot com>
- Subject: [xsl] New approach to grouping problem that doesn't use keys or axes
- From: "G. Ken Holman" <gkholman at CraneSoftwrights dot com>
- Date: Wed, 17 Oct 2001 08:52:29 -0400
- Reply-To: xsl-list at lists dot mulberrytech dot com
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@CraneSoftwrights.com
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