[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

RE: looping within a key's nodeset

Subject: RE: looping within a key's nodeset
From: "Jim Neff" <jneff@xxxxxxxxxxxxxxx>
Date: Fri, 25 Feb 2005 08:34:34 -0500
xsl for each nodeset
Matt,

I'm certainly no expert but I do a lot of pulling 'flat' data from a db like
yours and then reorganizing it using XSL stylesheets.

I don't know if this will help you or not, since I am using XSLT version 2,
but I make use of the for-each-group function.  It is incredibly easy to use
and understand.

For example, my code looks something like this:

<xsl:for-each-group select="Table" group-by="@CUST_CODE">
			
	<xsl:sort select="@CUST_CODE" order="ascending" />

</xsl:for-each-group>



Where @CUST_CODE is a unique ID from the database, this allows me then to
group together all of the rows that have the same customer code.  So my
output document would look something like this:

<customer>

	<customer_number>123</customer_number>
	<name>customer name here</name>

	...

</customer>

<customer>

	<customer_number>456</customer_number>
	<name>customer name here</name> 

	...

</customer>

...


But I also do this through multiple levels, so a customer could have many
orders, each order could have many line items, each line item could have one
or more methods of payment, etc....

So I nest my for-each-group statements and just use the unique id from the
database as the group-by attribute in my for-each-group command.  So the
second level of grouping for orders by customer would look something like
this:


<xsl:for-each-group select="Table" group-by="@ORDER_CODE">
			
	<xsl:sort select="@ORDER_CODE" order="ascending" />

</xsl:for-each-group>
 

This would be nested inside of the customer grouping like so:

<xsl:for-each-group select="Table" group-by="@CUST_CODE">
			
	<xsl:sort select="@CUST_CODE" order="ascending" />

	<xsl:element name="customer">

		<xsl:element name="customer_number">

			<xsl:value-of select="@customer_number"/>

		<xsl:element>

		<xsl:for-each-group select="current-group()"
group-by="@ORDER_CODE">
			
			<xsl:sort select="@ORDER_CODE" order="ascending" />

			<xsl:element name="order_number">

				<xsl:value-of select="@ORDER_CODE"/>

			<xsl:element>			

		</xsl:for-each-group>

	</xsl:element>

</xsl:for-each-group>


So my final output would be:

<customer>

	<customer_number>123</customer_number>

	<order>

		<order_number>56</order_number>

	</order>

	<order>

		<order_number>78</order_number>

	</order>

	...

</customer>

...

This is only two levels of grouping, but you can go on deeper (I do 4
levels).  This is extremely fast too (in addition to being easy to read).  I
use Saxon 8.1 and before I was doing this with a weird selection of
preceeding-sibling:* which took more than 5 mins to run some of my result
sets.  Usually this grouping takes less than 3 seconds.

Again, this is for XSLT version 2 only.  

Good luck,
Jim Neff


> -----Original Message-----
> From: Heckel, Matt , Ctr, OSD-PA&E 
> [mailto:Matthew.Heckel.ctr@xxxxxxx] 
> Sent: Friday, February 25, 2005 7:59 AM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject:  looping within a key's nodeset
> 
> Classification: UNCLASSIFIED
> 
> First of all.. Let me start by saying I'm not using XSL for a 
> classic enterprise type application.
> So what I'm asking, is a little beyond the typical questions 
> asked on this board.  It's not that its hard.. its just that 
> most people probably don't run into this situation and so 
> finding help or examples has been difficult.
> Much appreciation for those who respond.
> 
> I'm pulling data from a database.  The table in the db has multiple
> rows(elements) for one of the elements' attributes.  As in.. 
> ther is a one to many relationship between a particular 
> attribute within an element and other attributes within other 
> elements.  There are then 1 to many other attributes for each 
> of the attributes previously described. For example:
> 
> <doc>
> <ETL_2 SLOT_ACCT_NM="MH1553" SLOT_NM="MH1550" ALTRN_SLOT_NM="null"
> 	POT_ACCT_NM="MH1553-0" POT_NM="ally"
>         ALTRN_SLOT_1_NM="null"  ALTRN_SLOT_2_NM="null"/>
>         
> <ETL_2 SLOT_ACCT_NM="MH1553" SLOT_NM="MH1550" ALTRN_SLOT_NM="null"
> 	POT_ACCT_NM="MH1553-1" POT_NM="ally-1"
>         ALTRN_SLOT_1_NM="null"  ALTRN_SLOT_2_NM="null"/>
> 
> <ETL_2 SLOT_ACCT_NM="MH1553" SLOT_NM="MH1551" ALTRN_SLOT_NM="null"
> 	POT_ACCT_NM="MH1553-4" POT_NM="ally-4"
>         ALTRN_SLOT_1_NM="null"  ALTRN_SLOT_2_NM="null"/>
>         
> <ETL_2 SLOT_ACCT_NM="MH1553" SLOT_NM="MH1551" ALTRN_SLOT_NM="null"
> 	POT_ACCT_NM="MH1553-5" POT_NM="ally-5"
>         ALTRN_SLOT_1_NM="null"  ALTRN_SLOT_2_NM="null"/>
>        
> <ETL_2 SLOT_ACCT_NM="MH1554" SLOT_NM="MH1553" ALTRN_SLOT_NM="null"
> 	POT_ACCT_NM="MH1553-0" POT_NM="ally"
>         ALTRN_SLOT_1_NM="null"  ALTRN_SLOT_2_NM="null"/>
>        
> <ETL_2 SLOT_ACCT_NM="MH1554" SLOT_NM="MH1553" ALTRN_SLOT_NM="null"
> 	POT_ACCT_NM="MH1553-1" POT_NM="ally-1"
>         ALTRN_SLOT_1_NM="null"  ALTRN_SLOT_2_NM="null"/>
>   
> <ETL_2 SLOT_ACCT_NM="MH1554" SLOT_NM="MH1554" ALTRN_SLOT_NM="null"
> 	POT_ACCT_NM="MH1553-0" POT_NM="ally"
>         ALTRN_SLOT_1_NM="null"  ALTRN_SLOT_2_NM="null"/>
> 
> <ETL_2 SLOT_ACCT_NM="MH1554" SLOT_NM="MH1554" ALTRN_SLOT_NM="null"
> 	POT_ACCT_NM="MH1553-1" POT_NM="ally-1"
>         ALTRN_SLOT_1_NM="null"  ALTRN_SLOT_2_NM="null"/> </doc>
> 
> I need to group the data on the SLOT_ACCT_NM attribute to 
> create a nodesets with elements having the same 
> SLOT_ACCT_NMs.  Then for each nodeset, I need to iterate 
> through using UNIQUE SLOT_NM attributes as the index for the 
> loop.  Inside of that loop iteration, I then need to be able 
> to iterate through the nodeset using UNIQUE only POT_ACCT_NM 
> attributes to get all the POT_NMs associated with each unique 
> POT_ACCT_NM.  Essentially, I'm recombining data that has been 
> normalized for a db and I need to be able to loop inside of 
> loops all the while having access to all the elements in the 
> nodeset.  I've been using the Muenchian technique for my 
> initial grouping but am lost after passing the nodeset for 
> each group through an xsl:apply-templates call.  
> 
> <xsl:stylesheet version="1.0"
>    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
>    <xsl:key name="ETL_2_groups" match="ETL_2" use="@SLOT_ACCT_NM"/>
>    
>            <xsl:for-each
> ="ETL_2[generate-id()=generate-id(key('ETL_2_groups', 
> @SLOT_ACCT_NM))]">
>                
>                    <xsl:apply-templates 
> select="key('ETL_2_groups', @SLOT_ACCT_NM)"/>
>                
>            </xsl:for-each>
>        </doc>
>    </xsl:template>
>    <xsl:template match="ETL_2">
>       How do I loop through the nodeset thats been passed?  
> THANK YOU~ 
>    </xsl:template>
> </xsl:stylesheet>
> 
> 
> If I haven't explained my situation clearly enough I'd be 
> happy to try again..

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.