Re: [xsl] recursive sub-grouping

Subject: Re: [xsl] recursive sub-grouping
From: Mukul Gandhi <mukul_gandhi@xxxxxxxxx>
Date: Mon, 23 Aug 2004 07:10:31 -0700 (PDT)
Hi Robin,
  Please try this XSL. The XSL uses nodeset extension
function..

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:xalan="http://xml.apache.org/xalan";>
<xsl:output method="xml" indent="yes"/>
	
<xsl:key name="by-language" match="video-file"
use="language"/>
<xsl:key name="by-format" match="temp1/video-file"
use="format"/>
<xsl:key name="by-bandwidth" match="temp2/video-file"
use="bandwidth"/>
	
<xsl:template match="/video-files">
  <languages>
    <xsl:for-each select="video-file">
      <xsl:if test="generate-id(.) =
generate-id(key('by-language', language)[1])">
	<language>
	  <name>
	    <xsl:value-of select="language"/>
	  </name>
	  <xsl:variable name="rtf1">
	    <temp1>
	      <xsl:copy-of select="key('by-language',
language)"/>
	    </temp1>
	  </xsl:variable>
	  <formats>
	    <xsl:for-each
select="xalan:nodeset($rtf1)/temp1/video-file">
	      <xsl:if test="generate-id(.) =
generate-id(key('by-format', format)[1])">
	         <format>
		   <name>
		     <xsl:value-of select="format"/>
		   </name>
		   <xsl:variable name="rtf2">
		     <temp2>
		       <xsl:copy-of select="key('by-format',
format)"/>
		     </temp2>
		   </xsl:variable>
		   <bandwidths>
		     <xsl:for-each
select="xalan:nodeset($rtf2)/temp2/video-file">
			<xsl:if test="generate-id(.) =
generate-id(key('by-bandwidth', bandwidth)[1])">
			  <badwidth>
			    <name>
			      <xsl:value-of select="bandwidth"/>
			    </name>
			  </badwidth>
			</xsl:if>
		     </xsl:for-each>
		   </bandwidths>
		 </format>
	       </xsl:if>
  	     </xsl:for-each>
	   </formats>
	 </language>
       </xsl:if>
     </xsl:for-each>
   </languages>
 </xsl:template>
</xsl:stylesheet>

Regards,
Mukul

--- Robin Wyles <rob@xxxxxxxxxxxxxx> wrote:

> Hi,
> 
> I am stuck on a transformation that requires me to
> group and sub-group 
> a set of nodes based on their child nodes. My
> starting XML is as 
> follows:
> 
> -------------- SOURCE ---------------
> <?xml version="1.0"?>
> <video-files>
> 	<video-file>
> 		<language>English</language>
> 		<format>Real</format>
> 		<bandwidth>Low</bandwidth>
> 	</video-file>
> 	<video-file>
> 		<language>English</language>
> 		<format>Real</format>
> 		<bandwidth>High</bandwidth>
> 	</video-file>
> 	<video-file>
> 		<language>English</language>
> 		<format>QuickTime</format>
> 		<bandwidth>Low</bandwidth>
> 	</video-file>
> 	<video-file>
> 		<language>English</language>
> 		<format>QuickTime</format>
> 		<bandwidth>High</bandwidth>
> 	</video-file>
> 	<video-file>
> 		<language>French</language>
> 		<format>Real</format>
> 		<bandwidth>Low</bandwidth>
> 	</video-file>
> 	<video-file>
> 		<language>French</language>
> 		<format>Real</format>
> 		<bandwidth>High</bandwidth>
> 	</video-file>
> 	<video-file>
> 		<language>French</language>
> 		<format>QuickTime</format>
> 		<bandwidth>Low</bandwidth>
> 	</video-file>
> 	<video-file>
> 		<language>French</language>
> 		<format>QuickTime</format>
> 		<bandwidth>High</bandwidth>
> 	</video-file>
> </video-files>
> -------------------------
> 
> And the final XML is to be as follows:
> 
> ---------- FINAL ---------
> <?xml version="1.0"?>
> <languages>
> 	<language>
> 		<name>English</name>
> 		<formats>
> 			<format>
> 				<name>Real</name>
> 				<bandwidths>
> 					<bandwidth>
> 						<name>High</name>
> 					</bandwidth>
> 					[...]
> 				</bandwidths>				
> 			</format>
> 			[...]
> 		</formats>
> 	<language>
> 	[...]
> </languages>
> -----------------------------
> 
> I have searched the list for some pointers to a
> solution for this 
> problem and I have found plenty on grouping and
> sub-grouping but I have 
> had limited success in applying the techniques to my
> situation. The 
> initial grouping of the languages is no problem, but
> I am not sure how 
> to approach the sub-grouping on the current language
> group into format 
> groups, and then sub-group each of these into the
> bandwidth groups. I 
> have a feeling that I need to generate keys for the
> different 
> language/format/bandwidth combinations, but I am not
> sure how to 
> implement this. For what it's worth my current XSLT
> is as follows:
> 
> ------------ XSLT -------------
> <?xml version="1.0"?>
> <xsl:stylesheet version="1.0" 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
> 
> 	<xsl:key name="languages" match="video-file"
> use="language"/>
> 	<xsl:key name="formats" match="video-file"
> use="concat(language, '+', 
> format)"/>
> 	<xsl:key name="bandwidths" match="video-file"
> use="concat(language, 
> '+', format, '+', bandwidth)"/>
> 
> 	<xsl:template match="video-files">
> 		<languages>
> 			<xsl:for-each 
>
select="video-file[generate-id(.)=generate-id(key('languages',
> 
> language)[1])]">
> 				<xsl:for-each select="key('languages',
> language)">
> 					<xsl:sort select="format"/>
> 					<language>
> 						<xsl:if test="position() = 1">
> 							<name><xsl:value-of
> select="language"/></name>
> 						</xsl:if>
> 						<formats>
> 							<!--- Need to do sub grouping here -->
> 						</formats>
> 					</language>
> 				</xsl:for-each>
> 			</xsl:for-each>
> 		</languages >
> 	</xsl:template>
> </xsl:stylesheet>
> --------------------------------
> 
> If anyone has any advice on the best way to approach
> this problem (XSLT 
> 1.0 only if possible), I would appreciate it.
> 
> Thanks,
> 
> Robin



		
_______________________________
Do you Yahoo!?
Win 1 of 4,000 free domain names from Yahoo! Enter now.
http://promotions.yahoo.com/goldrush

Current Thread