Re: [xsl] xsl:for - Only for existing nodes, how?

Subject: Re: [xsl] xsl:for - Only for existing nodes, how?
From: "Nick Fitzsimons" <nick@xxxxxxxxxxxxxx>
Date: Tue, 21 Feb 2006 16:37:07 -0000 (GMT)
> Hello,
>
> I'm trying to figure out the best way to transform a node-set only if it
> includes certain nodes, Lets assume I have the following xml structure:
>
> <tree>
>    <controls>
>       <control>
>          <dummy><data>some data</data></dummy>
>          <item1><data>some data</data></item1>
>          <item2><data>some data</data></item2>
>       </control>
>       <control>
>          <dummy><data>some data</data></dummy>
>          <item1><data>some data</data></item1>
>          <item2><data>some data</data></item2>
>       </control>
>    </controls>
> </tree>
>
> I want to select the values of item1's data and item2's data so I'm doing
> this:
> <xsl:for-each select="/tree/controls/control">
>    <xsl:value-of select="item1/data"/>
>    <xsl:value-of select="item2/data"/>
> </xsl:for-each>
>
> This is all fine but my problem begins when there're more "control" nodes
> with no item1 or item2 children. So if there's one more "control" child
> (for
> the example above) which is empty then the for loop will itterate 3 times
> while I need it to itterate only 2 times for real values. I thought about
> doing something like:
> <xsl:for-each select="/tree/controls/control/item1">
>     <xsl:value-of select="data"/>
>     <xsl:value-of select="../item2/data"/>
> </xsl:for-each>
>
> But I'm hoping that there's a more celver way to do what I want.
>

You could use:

<xsl:for-each select="/tree/controls/control[item1 | item2]">

which would only process "control" nodes that had either "item1" or
"item2" children (or both). Or you could use a template-based approach:

<!-- Do nothing for "control" nodes without anything special about them -->
<xsl:template match="control" />

<!-- Keep processing for "control" nodes with "item1" and/or "item2"
children -->
<xsl:template match="control[item1 | item2]">
   <xsl:apply-templates />
</xsl:template>

<xsl:template match="item1 | item2">
   <xsl:apply-templates />
</xsl:template>

<xsl:template match="data">
   <xsl:apply-templates />
</xsl:template>

<xsl:template match="dummy" />

HTH,

Nick.
-- 
Nick Fitzsimons
http://www.nickfitz.co.uk/

Current Thread