Subject: Re: [xsl] XSLT 1.0: How to spit out unique values at *second* level of grouping From: "Mukul Gandhi" <gandhi.mukul@xxxxxxxxx> Date: Tue, 24 Oct 2006 23:56:50 +0530 |
Using node-set extension function this is easy to solve. Below is the modified stylesheet (tested with IE 7):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0">
<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> <xsl:variable name="rtf"> <xsl:for-each select="//food_type[food_type_id=1 or food_type_id=4]"> <xsl:copy-of select="//food[food_id = current()/food_id]" /> </xsl:for-each> </xsl:variable> <xsl:for-each select="msxsl:node-set($rtf)/food[count(. | key('food', food_id)[1])=1]"> <li><xsl:value-of select="name"/></li> </xsl:for-each> </p> </body> </html> </xsl:template>
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 ------------------------------------------------------------------------
-- Regards, Mukul Gandhi
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] XSLT 1.0: How to spit out uni, Henesy, Susan | Thread | RE: [xsl] XSLT 1.0: How to spit out, Henesy, Susan |
[xsl] Combining 2 template matches, Aaron Johnson | Date | Re: [xsl] Error when switching to j, footh |
Month |