[xsl] XSLT 1.0: How to spit out unique values at *second* level of grouping

Subject: [xsl] XSLT 1.0: How to spit out unique values at *second* level of grouping
From: "Henesy, Susan" <Susan.Henesy@xxxxxxxxx>
Date: Tue, 24 Oct 2006 08:23:56 -0700
Dear List,

Thank you for encouraging me to re-post my question.  I'm glad there was
just a strange digest error that ate my post!!

Based on the XML file I have, I want to select two Food_Types, and spit
out a distinct list of Foods that belong to the two Food_Type_Ids.  I
need to prove that multiple FOOD_IDs can belong to multiple FOOD_TYPEs -
and that I can spit out those FOOD_IDs uniquely for the FOOD_TYPE_IDs I
choose.

This seems like it would be simple, but it is proving to be beyond me.
You will understand the dilemma when you see how the two node groups are
structured - similar to data I am working with from a database here at
the office.

Immediately below is my XML file - and below that, XSL code that I am
working on. I thought that if I used a "for-each" loop for each FOOD
TYPE and then nested another "for-each" loop within that one -- which
would use KEYS and the COUNT[] method to return only unique FOODS --
that that would work, but it doesn't.

I tried to use the "generate-id" idea but that didn't work, either.

The best I can guess is that since my first "for-each" loop is looping
through each FOOD_ID found in FOOD_TYPE (which has the duplicate  info)
...generate_id didn't work ... because it just created a unique id for
something that repeated.

As for the count[] method not working in the nested "for-each" loop ...
I am stumped ... I must not understand how those nodes find each other.

Basically, if I choose FOOD_TYPE where the food_type_id = 1 or
food_type_id = 4, I do *NOT* want to see "Belgian Waffles" repeat itself
just because it is in those two groups.  However, the output I get, no
matter HOW HARD I TRY, is always:

*******************************************************************
Show a unique list of Breakfast Items that belong to food types
"Waffles" and "Combos".

1) WAFFLES 4) COMBO BREAKFASTS

1) Belgian Waffles <-- Belgian waffles appears TWICE!!!!
1) Belgian Waffles <-- Belgian waffles appears TWICE!!!!
2) Strawberry Belgian Waffles
3) Berry-Berry Belgian Waffles
5) Homestyle Breakfast
*******************************************************************

Below are my XML and XSL files.  Thank you in advance for any help that
anyone can give me!!

---------------------------------------------------------------
FOOD.XML
---------------------------------------------------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<breakfast_menu>
	<food>
    <food_id>1</food_id>
		<name>Belgian Waffles</name>
		<price>$5.95</price>
		<description>two of our famous Belgian Waffles with
plenty of real maple syrup</description>
		<calories>650</calories>
	</food>
	<food>
    <food_id>2</food_id>
		<name>Strawberry Belgian Waffles</name>
		<price>$7.95</price>
		<description>light Belgian waffles covered with
strawberries and whipped cream</description>
		<calories>900</calories>
	</food>
	<food>
    <food_id>3</food_id>
		<name>Berry-Berry Belgian Waffles</name>
		<price>$8.95</price>
		<description>light Belgian waffles covered with an
assortment of fresh berries and whipped cream</description>
		<calories>900</calories>
	</food>
	<food>
    <food_id>4</food_id>
		<name>French Toast</name>
		<price>$4.50</price>
		<description>thick slices made from our homemade
sourdough bread</description>
		<calories>600</calories>
	</food>
	<food>
    <food_id>5</food_id>
		<name>Homestyle Breakfast</name>
		<price>$6.95</price>
		<description>two eggs, bacon or sausage, toast, and our
ever-popular hash browns</description>
		<calories>950</calories>
	</food>

  <!-- Food Type 1: WAFFLES -->
  <food_type>
    <food_type_id>1</food_type_id>
    <food_type_name>WAFFLES</food_type_name>
    <food_id>1</food_id>
  </food_type>
  <food_type>
    <food_type_id>1</food_type_id>
    <food_type_name>WAFFLES</food_type_name>
    <food_id>2</food_id>
  </food_type>
  <food_type>
    <food_type_id>1</food_type_id>
    <food_type_name>WAFFLES</food_type_name>
    <food_id>3</food_id>
  </food_type>
  <!-- Food Type 2: FRENCH TOAST -->
  <food_type>
    <food_type_id>2</food_type_id>
    <food_type_name>FRENCH TOAST</food_type_name>
    <food_id>4</food_id>
  </food_type>
  <!-- Food Type 3: TRADITIONAL BREAKFASTS -->
  <food_type>
    <food_type_id>3</food_type_id>
    <food_type_name>TRADITIONAL BREAKFASTS</food_type_name>
    <food_id>5</food_id>
  </food_type>
  <!-- Food Type 4: COMBO BREAKFASTS -->
  <food_type>
    <food_type_id>4</food_type_id>
    <food_type_name>COMBO BREAKFASTS</food_type_name>
    <food_id>5</food_id>
  </food_type>
  <food_type>
    <food_type_id>4</food_type_id>
    <food_type_name>COMBO BREAKFASTS</food_type_name>
    <food_id>1</food_id>
  </food_type>

</breakfast_menu>

---------------------------------------------------------------
FOOD.XSL
---------------------------------------------------------------
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0">

<xsl:output method="html"/>



  <xsl:key name="food" match="food" use="food_id"/>
  <xsl:key name="foodType" match="food_type" use="food_type_id"/>



  <xsl:template match="/">
    <html>
      <body>

        <p>
          <h3>Example</h3>
        <p>

            <b>Show a unique list of Breakfast Items that belong to food
types "Waffles" and "Combos".</b>

          </p>

          <!-- SHOW HEADER : Waffles = 1, Combos = 4. -->

          <xsl:for-each select="//food_type[count(. |
key('foodType',food_type_id)[1]) = 1]">

             <xsl:variable name="foodType" select="food_type_id"/>
            <xsl:if test="$foodType = 1 or $foodType=4">

              <u>
                <xsl:value-of select="food_type_id"/>)<xsl:text>
</xsl:text><xsl:value-of select="food_type_name"/>
              </u>

              <xsl:text> </xsl:text>
            </xsl:if>



          </xsl:for-each>
          <br></br>




<!--||**************************************************************
           || TROUBLE AREA - CAN'T GET DISTINCT FOOD IDS!!!!!

||*************************************************************-->

                <xsl:for-each select="//food_type[food_type_id=1 or
food_type_id=4]">
                        <xsl:sort select="food_id"/>
                        <xsl:variable name="foodType"
select="food_type_id"/>
                        <xsl:variable name="foodID" select="food_id"/>

                       <xsl:for-each select="//food[count(. |
key('food', $foodID)[1])=1]">
                              <li><xsl:value-of select="name"/></li>
                        </xsl:for-each>

                 </xsl:for-each>



<!--||**************************************************************-->


        </p>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

------------------------------------------------------------------------
---
END OF POST
------------------------------------------------------------------------
---

Current Thread