xsl-list
[Top] [All Lists]

[xsl] XSLT 2.0 multi-level grouping challenge/problem

2007-05-24 07:25:17
Consider this multi-level grouping problem for XSLT 2.0.

I think I should be able to do this with for-each-group, but I am so far 
frustrated. I usually find the most baroque way of accomplishing a programming 
task when I first start, only later learning how to pare it down.

I am told that Blaise Pascal once began a letter to a friend saying, "Please 
excuse this long letter. I didn't have time to write a short one."

The input document is a list of organ donors.
The donor element lists the city and state of the donor and the organ to be 
donated.

The output should be a table of four columns.

The table should have a new row when the value of the <state/> element changes 
with the value of the state appearing in column one.

The table should have a new row when the value of the <city/> element changes 
with the value of the city appearing in column two.

The table should have a new row when the value of the <organ/> element changes, 
listing the organ in column three and the count of all organs of that type in 
the current city and the current state in column four.

The rows of the table should be sorted by state, city, and organ.

I've been puzzling over this for several hours. I think the correct approach is 
to create an in-memory XML document containing one element for each state, a 
second in-memory XML document containing an element for each city and state 
combination, and a third in-memory document for each city, state, and organ 
combination. I would then process the successive rows in the states table, 
using the values as a key into the cities table, using the values as a key into 
the organs table, ... well, I kind of lose track here.

Surely one of you has done something like this. Would you be so kind as to 
explain how it's done?

Thank you.

<states>
  <state></state>
<states>

<cities>
  <city></city>
  <state></state>
</cities>

<organs>
  <organ></organ>
  <city></city>
  <state></state>
</organs>

<?xml version="1.0" encoding="windows-1252"?>
<donors>
  <donor>
    <city>Pittsburgh</city>
    <state>Pennsylvania</state>
    <organ>liver</organ>
  <donor>
  <donor>
    <city>Pittsburgh</city>
    <state>Pennsylvania</state>
    <organ>liver</organ>
  <donor>
  <donor>
    <city>Pittsburgh</city>
    <state>Pennsylvania</state>
    <organ>lungs</organ>
  <donor>
  <donor>
    <city>Pittsburgh</city>
    <state>Pennsylvania</state>
    <organ>lungs</organ>
  <donor>
  <donor>
    <city>Pittsburgh</city>
    <state>Pennsylvania</state>
    <organ>kidney</organ>
  <donor>
  <donor>
    <city>Akron</city>
    <state>Ohio</state>
    <organ>kidney</organ>
  <donor>
  <donor>
    <city>Akron</city>
    <state>Ohio</state>
    <organ>kidney</organ>
  <donor>
  <donor>
    <city>Columbus</city>
    <state>Ohio</state>
    <organ>lungs</organ>
  <donor>
  <donor>
    <city>Columbus</city>
    <state>Ohio</state>
    <organ>lungs</organ>
  <donor>
  <donor>
    <city>Columbus</city>
    <state>Ohio</state>
    <organ>lungs</organ>
  <donor>
  <donor>
    <city>Cleveland</city>
    <state>Ohio</state>
    <organ>liver</organ>
  <donor>
  <donor>
    <city>Cleveland</city>
    <state>Ohio</state>
    <organ>heart</organ>
  <donor>
</donors>

<table>
  <row> &lt;-- Header Row --&gt;
    <td>State</td>
    <td>City</td>
    <td>Organ</td>
    <td>Count</td>
  </row>
  <row> &lt;-- First appearance of "Ohio" --&gt;
    <td>Ohio</td>
    <td></td>
    <td></td>
    <td></td>
  </row>
  <row> &lt;-- First appearance of "Akron" in "Ohio" --&gt;
    <td></td>
    <td>Akron</td>
    <td></td>
    <td></td>
  </row>
  <row> &lt;-- First appearance of "kidney" in "Akron" in "Ohio" --&gt;
    <td></td>
    <td></td>
    <td>kidney</td> &lt;-- count of all kidneys from Akron, Ohio --&gt;
    <td>2</td>
  </row>
  <row> &lt;-- First appearance of "Columbus" in "Ohio" --&gt;
    <td></td>
    <td>Columbus</td>
    <td></td>
    <td></td>
  </row>
  <row> &lt;-- First appearance of "lungs" in "Columbus" in "Ohio" --&gt;
    <td></td>
    <td></td>
    <td>lungs</td> &lt;-- count of all lungs from Columbus, Ohio --&gt;
    <td>2</td>
  </row>
  <row> &lt;-- First appearance of "Cleveland" in "Ohio" --&gt;
    <td></td>
    <td>Cleveland</td>
    <td></td>
    <td></td>
  </row>
  <row> &lt;-- First appearance of "liver" in "Cleveland" in "Ohio" --&gt;
    <td></td>
    <td></td>
    <td>liver</td>
    <td>1</td> &lt;-- count of all livers from Cleveland, Ohio --&gt;
  </row>
  <row> &lt;-- First appearance of "heart" in "Cleveland" in "Ohio" --&gt;
    <td></td>
    <td></td>
    <td>liver</td>
    <td>1</td> &lt;-- count of all hearts from Cleveland, Ohio --&gt;
  </row>
  <row> &lt;-- First appearance of "Pennsylvania" --&gt;
    <td>Pennsylvania</td>
    <td></td>
    <td></td>
    <td></td>
  </row>
  <row> &lt;-- First appearance of "Pittsburgh" in "Pennsylvania" --&gt;
    <td></td>
    <td>Pittsburgh</td>
    <td></td>
    <td></td>
  </row>
  <row> &lt;-- First appearance of "kidney" in "Pittsburgh" in "Pennsylvania" 
--&gt;
    <td></td>
    <td></td>
    <td>kidney</td> &lt;-- count of all kidneys from Pittsburgh, Pennsylvania 
--&gt;
    <td>1</td>
  </row>
  <row> &lt;-- First appearance of "liver" in "Pittsburgh" in "Pennsylvania" 
--&gt;
    <td></td>
    <td></td>
    <td>liver</td>
    <td>2</td> &lt;-- count of all livers from Pittsburgh, Pennsylvania --&gt;
  </row>
  <row> &lt;-- First appearance of "lungs" in "Pittsburgh" in "Pennsylvania" 
--&gt;
    <td></td>
    <td></td>
    <td>lungs</td> &lt;-- count of all lungs from Pittsburgh, Pennsylvania 
--&gt;
    <td>2</td>
  </row>
</table>

-- 
Charles Knell
cknell(_at_)onebox(_dot_)com - email

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--