Jump to content

Nested for-each?


Guest Gasoline

Recommended Posts

Guest Gasoline

Howdy! :) I'm a beginner with xml and xsl so the question might be a simple one.I would like to transform a xml document containing a list which in turn contains a list.I don't know the number of elements in the list, it can vary.My solution involves a nested for-each but it doesn't work.Like this:I might have a lot of boxes, each having a label and various number of surprise items.The structure of the xml code:<document>---<box>------<label/>------<surpriselist>---------<surpriseitem>------</surpriselist>---</box></document>The xsl code I tried without succeeding:<xsl:for-each select="document/box"> <tr> <td><xsl:value-of select="label"/></td> <td></td> </tr> <tr> <td>Surprises in the box</td> <td></td> </tr> <xsl:for-each select="document/box/surpriselist"> <tr> <td></td> <td><xsl:value-of select="surpriseitem"></td> </tr> </xsl:for-each></xsl:for-each>The output I was looking for was something like this:Box1Surprises in the box: drink pencil CDBox2Surprises in the box: guitarBox3Surprises in the box: phone book skateboard sandwitchPlease help! This shouldn't be that hard, but I just can't figure out why my solution isn't working. :) Thanks in advance!

Link to comment
Share on other sites

I think you just have too much qualification on the inner for-each. So instead of:

<xsl:for-each select="document/box">...<xsl:for-each select="document/box/surpriselist">...

I think you need to use:

<xsl:for-each select="document/box">...<xsl:for-each select="surpriselist">...

The inner for-each will then be applied to the target of the outer for-each.

Link to comment
Share on other sites

Good catch Reg Edit :) . I was planning to suggest creating a pulling scheme. Something I myself had problems with... I solved them with this:

	<xsl:template name="menu" match="menu">		<ul>			<xsl:for-each select="item">				<li>					<xsl:if test="menu">						<xsl:attribute name="class">submenu</xsl:attribute>					</xsl:if>					<a href="{link}">						<xsl:value-of select="title"/>					</a>					<xsl:if test="menu">						<xsl:apply-templates select="menu"/>					</xsl:if>				</li>			</xsl:for-each>		</ul>	</xsl:template>

However, this code expects that the currect list and the surpriselist have the same name ("menu" in my case). If you have to handle different element names, the situation might get a bit trickier. Not handling particular elements on particular levels would make it a real challenge too.

Link to comment
Share on other sites

"The inner for-each will then be applied to the target of the outer for-each"Great! Reg Edit is right.But if you write:<xsl:for-each select="document/box">...<xsl:for-each select="surpriselist"><xsl:value-of select ="surpriseitem"></xsl:for-each>..It only returns the first surpriseitem in the surpriselist.You should write:<xsl:for-each select="document/box">...<xsl:for-each select="surpriselist/surpriseitem"><xsl:value-of select ="."></xsl:for-each>..With each surpriseitem, select the current value (in Xpath syntax it is "." )Or if you have more than one surpricelist, you can list the surpriceitem and use a blank line to seperate each surpricelist as follow:<xsl:for-each select="document/box">...<xsl:for-each select="surpriselist"><xsl:for-each select="surpriseitem"><xsl:value-of select ="."><br/></xsl:for-each><br/></xsl:for-each>..Try it on! You will have what u want :)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...