Re: [xsl] recursive sub-grouping

Subject: Re: [xsl] recursive sub-grouping
From: Robin Wyles <rob@xxxxxxxxxxxxxx>
Date: Mon, 23 Aug 2004 21:07:53 +0200
Mukal,

That works perfectly, you're a star, thanks!

Robin

On 23 Aug 2004, at 16:10, Mukul Gandhi wrote:

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