• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 822
  • Last Modified:

Selecting new variable from list for each iteration of for-each loop

Hi All,

I'm trying to include in my XSLT file a variable containing multiple elements which I need to use during a for-each loop. The variable could be as below in theory:

<xsl:variable name="colorPalette">
   <color value="red"/>
   <color value="blue"/>
   <color value="green"/>
</xsl:variable>

During a for-each loop, I need to use the values - a different one for each iteration. Here's an example of how I thought it might work based on a similar solution I found:

<xsl:for-each select="...">
   <set>
      <xsl:attribute name="color">
         <xsl:for-each select="$colorPalette/color[not(@value = preceding::*/@value)]">
            <xsl:value-of select="@value"/>
         </xsl:for-each>
      </xsl:attribute>
   </set>
</xsl:for-each>

What would be the best way to accomplish this? The main for-each loop needs to remain a loop, but the variable process could use templates or some other approach. Thanks in advance!
0
PrecisionDotNet
Asked:
PrecisionDotNet
  • 4
  • 2
  • 2
  • +1
2 Solutions
 
sweetfa2Commented:
<set color="redbluegreen"/>
<set color="redbluegreen"/>

or


<set color="red"/>
<set color="blue"/>
<set color="green"/>
0
 
zc2Commented:
If you're using a MSXML processor, you can give a try to msxsl:node-set() extension, which converts the variable value to a node-set.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
	<xsl:template match="/root">
		<xsl:variable name="colorPalette">
		   <color value="red"/>
		   <color value="blue"/>
		   <color value="green"/>
		</xsl:variable>
		
		<xsl:for-each select="item">
		   <set>
		   	<xsl:variable name="p" select="position()"/>
		      <xsl:attribute name="color">
		       <xsl:value-of select="msxsl:node-set($colorPalette)/color[$p]/@value"/>
		      </xsl:attribute>
		   </set>
		</xsl:for-each> 
	</xsl:template>
</xsl:stylesheet>

Open in new window

0
 
sweetfa2Commented:
      <xsl:for-each select=".">
      	<xsl:for-each select="$colorPalette/color">
	      <xsl:variable name="index" select="position()"/>
         <set>
	         	<xsl:attribute name="pos">
	         		<xsl:value-of select="$index"/>
	         		</xsl:attribute>
            <xsl:attribute name="color">
	            <xsl:value-of select="$colorPalette/color[$index]/@value"/>
            </xsl:attribute>
         </set>
         </xsl:for-each>
      </xsl:for-each> 

Open in new window

0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
Geert BormansCommented:
This will only work in XSLT2.0 I am afraid.
Or you need to use an extension
a lot of processors support exslt:nodeset()

If you put some XML tags in a variable,
you can't simply use that as a lookup using XPath
because the XML elements are a Result Tree Fragment,
and XSLT1 does not cast a RFT to a node-set() automatically
(XSLT2 does)

In order for me to show you a solution that would possibly allow this,
I need to know which processor you are using.
Is this .net? let me know

Other options are
- having the values for the variable in a seperate XML document and use document() to get it
- put the values in a string with a seperator and make a recursive function to loop over the string (bit awkward, but it works)
- start using XSLT2 (there is a saxon.net version)
0
 
Geert BormansCommented:
Coming in late I see,
- zc2 is spot on (as usual), offering a solution for msxml
- sweetfa2 fails to explain that his solution only works in XSLT2 (Saxon9)

I have adapted zc2's solution for working with Xalan, Saxon6, LibXSLT and 4Suite XSLT
(just changed the use of node-set in a different namespace, have not checked the XSLT, trusting that one)
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="xmlns:exslt="http://exslt.org/common" exclude-result-prefixes="exsl">
<xsl:output method="xml" indent="yes"/>
	<xsl:template match="/root">
		<xsl:variable name="colorPalette">
		   <color value="red"/>
		   <color value="blue"/>
		   <color value="green"/>
		</xsl:variable>
		
		<xsl:for-each select="item">
		   <set>
		   	<xsl:variable name="p" select="position()"/>
		      <xsl:attribute name="color">
		       <xsl:value-of select="exsl:node-set($colorPalette)/color[$p]/@value"/>
		      </xsl:attribute>
		   </set>
		</xsl:for-each> 
	</xsl:template>
</xsl:stylesheet>

Open in new window

0
 
PrecisionDotNetAuthor Commented:
Thanks for the responses! Sorry I didn't give more details in my question. This would be run on a SharePoint server (specifically Microsoft's SharePoint Online servers), the XSLT file stored in a document library and read in using JavaScript.
0
 
Geert BormansCommented:
Then you are using msxml and zc2's solution should work
0
 
PrecisionDotNetAuthor Commented:
It works like a charm! Thanks for the answers and explanations.
0
 
zc2Commented:
you're welcome
0
 
Geert BormansCommented:
welcome
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 2
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now