RE: [xsl] xsl:key on variable containing result of apply-templates

Subject: RE: [xsl] xsl:key on variable containing result of apply-templates
From: "Michael Kay" <michael.h.kay@xxxxxxxxxxxx>
Date: Mon, 25 Nov 2002 09:20:25 -0000
> Hello,
> This is my first post to this list and I apologize for it's 
> length.  My 
> question basically is whether it is possible to create a key 
> on a variable 
> which contains the result of applying a template?

This is my umpteenth answer on this list and I apologize for its
brevity.

The answer is yes. When you declare a key using xsl:key then you can use
the key() function referencing that key with ANY source document
including a temporary tree. If necessary, use xsl:for-each to ensure
that the correct document is current before calling key().

Michael Kay
Software AG
home: Michael.H.Kay@xxxxxxxxxxxx
work: Michael.Kay@xxxxxxxxxxxxxx 


  In my real 
> stylesheet 
> and xml the template which creates the node-set I would like 
> to create the 
> key on is much more complicated than the example I have given 
> below - but 
> the concept is the same.  I apply-templates to the source 
> document and the 
> result tree fragment is kept in a variable ($alphabet). I 
> convert this to a 
> node-set ($alphabet-exslNodeSet) and then use that node-set 
> in another 
> template.  It works but is pretty slow - I think it would be 
> much faster if 
> I were able to create a key on the node-set (each item in the 
> node set is 
> used multiple times).  I can't see how to do that - it looks like my 
> attempt below gives me the code in the variable, not the 
> result.  I know I 
> can't use a variable in the key's match attribute, so I'm at 
> a loss how to 
> do this.
> Thanks for any suggestions,
> Grainne.
> 
> The Stylesheet:
> ============
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet version="1.0" 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
> xmlns:saxon="http://icl.com/saxon"; 
> xmlns:exsl="http://exslt.org/common";
> exclude-result-prefixes="ss"
> extension-element-prefixes="exsl saxon">
> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
> 
> 	<xsl:variable name="alphabet">
> 		<xsl:apply-templates 
> select="/test/alphabetList/alphabet" mode="loadList"/>
> 	</xsl:variable>
> 
> 	<xsl:variable 
> name="alphabet-NodeSet" 
> select="document('')/xsl:stylesheet/xsl:variable[@name='alphabet']" />
> 	<xsl:variable name="alphabet-exslNodeSet" 
> select="exsl:node-set($alphabet)"/>
> 	
> 	<xsl:key name="myKey" 
> match="/*/xsl:variable[@name='alphabet']" use="@col"/>
> 
> 	<xsl:template match="alphabet" mode="loadList">
> 		<xsl:copy-of select="."/>
> 	</xsl:template>
> 
> 	<xsl:template match="*"/>
> 		
> 	<xsl:template match="/">
> 		Value of alphabet variable is:<xsl:text>
> 		</xsl:text> <xsl:copy-of select="$alphabet"/><xsl:text>
> 		</xsl:text>
> 		Value of alphabet-NodeSet varaible is (I think 
> this is what I get in the 
> key!!)<xsl:text>
> 		</xsl:text><xsl:copy-of 
> select="$alphabet-NodeSet"/><xsl:text>
> 		</xsl:text>
> 		Value of alphabet-exslNodeSet variable is <xsl:text>
> 		</xsl:text><xsl:copy-of 
> select="$alphabet-exslNodeSet"/>	<xsl:text>
> 		</xsl:text>
> 		<xsl:apply-templates select="test/numbers"/>	
> 	</xsl:template>
> 	
> 		
> 	<xsl:template match="numbers">
> 		<xsl:for-each select="number">
> 			<xsl:variable name="curPosition" 
> select="position()"/>
> 			Using the key to get the alphabet 
> element (THIS is what I'd like to do 
> since each node in the set is used multiple times):
> 			<number value="{.}">
> 			<xsl:for-each select="document('')">
> 				<xsl:copy-of 
> select="key('myKey',$curPosition)"/>
> 			</xsl:for-each>
> 			</number>
> 			Using the exslNodeSet variable to get 
> the alphabet element (what I am 
> doing but which is very slow in my real code):
> 			<number value="{.}">
> 			<xsl:copy-of 
> select="$alphabet-exslNodeSet/alphabet[@col=$curPosition]"/>
> 			</number>
> 			<xsl:text>
> 			</xsl:text>			
> 		</xsl:for-each>	
> 	</xsl:template>	
> 	
> </xsl:stylesheet>
> 
> 
> 
> Example xml:
> ==========
> <?xml version="1.0" encoding="UTF-8"?>
> <test>
> 	<alphabetList>
> 		<alphabet col="1">a</alphabet>
> 		<alphabet col="2">b</alphabet>
> 		<alphabet col="3">c</alphabet>
> 		<alphabet col="4">d</alphabet>
> 		<alphabet col="5">e</alphabet>
> 	</alphabetList>
> 	<numbers>
> 		<number>one</number>
> 		<number>two</number>
> 		<number>three</number>
> 		<number>four</number>
> 		<number>five</number>
> 	</numbers>
> </test>
> 
> Result (tidied up a little):
> ====================
> <?xml version="1.0" encoding="UTF-8"?>
> Value of alphabet variable is:
> <alphabet col="1">a</alphabet>
> <alphabet col="2">b</alphabet>
> <alphabet col="3">c</alphabet>
> <alphabet col="4">d</alphabet>
> <alphabet col="5">e</alphabet>
> 		
> Value of alphabet-NodeSet varaible is (I think this is what I 
> get in the key!!) <xsl:variable 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; 
> xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
> xmlns:saxon="http://icl.com/saxon"; 
> xmlns:exsl="http://exslt.org/common"; 
> name="alphabet">		
>     <xsl:apply-templates select="/test/alphabetList/alphabet" 
> mode="loadList"/> </xsl:variable>
> 		
> Value of alphabet-exslNodeSet variable is
> <alphabet col="1">a</alphabet>
> <alphabet col="2">b</alphabet>
> <alphabet col="3">c</alphabet>
> <alphabet col="4">d</alphabet>
> <alphabet col="5">e</alphabet>
> 		
> 			Using the key to get the alphabet 
> element (THIS is what I'd like to do 
> since each node in the set is used multiple times):
> 			<number value="one"/>
> 			Using the exslNodeSet variable to get 
> the alphabet element (what I am 
> doing but which is very slow in my real code):
> 			<number value="one">
>     			<alphabet col="1">a</alphabet>
> 			</number>
> 			
> ...<snip>...			
> 			Using the key to get the alphabet 
> element (THIS is what I'd like to do 
> since each node in the set is used multiple times):
> 			<number value="five"/>
> 			Using the exslNodeSet variable to get 
> the alphabet element (what I am 
> doing but which is very slow in my real code):
> 			<number value="five">
>     			<alphabet col="5">e</alphabet>
> 			</number>
> 			
> 
> 
> 
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> 


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread