Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

XSLT Itaration through for-each select statment 2

Status
Not open for further replies.

AGus01

Technical User
Sep 6, 2005
54
GB
Newbie to XSLT. Hi I have this for each statment. I wish to make sure that every other time it Itartates through this loop it runs one or anouther set of XSLT code. hope that makes sence. Think that I probably need some sort of If statment. Please help much appreciated.


<xsl:for-each select="vacancies">
<xsl:value-of select="EmployerName"/> - <xsl:value-of select="ProgrammeDesc"/>
<xsl:text>This should only appear with 1,3,5.. etc iteration</xsl:text>
<xsl:value-of select="VacancyDesc"/>
</xsl:for-each>
 
Try this.
[tt]
<xsl:for-each select="[red]//[/red]vacancies">
<xsl:if test="position() mod 2 = 1">
<!-- get the value-of statements here -->
</xsl:if>
</xsl:for-each>
[/tt]
 
Don't use the double-backslash, it will search the entire tree and therefore is very inefficient. Always specify the full path where you can.

Jon

"I don't regret this, but I both rue and lament it.
 
>Don't use the double-backslash...
But, can you see through the screen what the op has as xml?
 
By the look of it, "vacancies" is already a node-set. Best not to get into bad habits when you are a beginner.

Jon

"I don't regret this, but I both rue and lament it.
 
But exactly it looks like it is not a node-set for me! It is not a habit neither, good or bad. descendant-or-self is a royally respectable axis, for beginners or more advanced. In any case, I have no other opinion on other issue and I have no intention to debat efficiency on the moving sand.
 
Hi,

I tried 'tsuji' code and it did exactly what I wanted. I then tried omitting the two forward slashes from the for:each select statment and the code still works as expected.

From my limited understanding putting the two forward slashes in mean that the XSLT parser scans all nodes of the XML for the vacancy element (not just the current node that it is in). Is this correct? is this the correct terminology?

Thanks for your Help Gus
 
Yes, you are correct and correct terminology.

I see a lot of XSL templates that use "//" all over the place. In small XML files its ok, but the transform can get *really* slow with large files. Also, it makes the whole thing a lot easier to read, understand and debug if you specify the full paths of node-sets when you can.

Just doing my bit for semantics :)

Jon

"I don't regret this, but I both rue and lament it.
 
// stands for the axis of descendant-or-self. Feel no fetter to use it because everything has a judicious use. Take for instance this.

example 1
[tt]
<root ex="1">
<x>
<y>1</y>
</x>
<x>
<y>2</y>
</x>
<x>
<y>3</y>
</x>
<x>
<y>4</y>
</x>
<x>
<y>5</y>
</x>
<root>
[/tt]
Your xsl can be this.
[tt][teal]
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="<xsl:eek:utput method="text" />
<xsl:template match="/">
<xsl:for-each select="//x"> <!-- or .//x -->
<xsl:if test="position() mod 2 = 1">
[<xsl:value-of select="y" />]
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
[/teal][/tt]
[II} Example 2 : suppose it is a level deeper.
[tt][purple]
<root ex="2">
<z>
<x>
<y>1</y>
</x>
<x>
<y>2</y>
</x>
<x>
<y>3</y>
</x>
<x>
<y>4</y>
</x>
<x>
<y>5</y>
</x>
</z>
<z>
<x>
<y>11</y>
</x>
<x>
<y>12</y>
</x>
<x>
<y>13</y>
</x>
<x>
<y>14</y>
</x>
<x>
<y>15</y>
</x>
</z>
</root>
[/purple][/tt]
Then this is a viable xsl with no where appearing //x, but with //z somewhere.
[tt][blue]
<xsl:stylesheet version="1.0" xmlns:xsl="<xsl:eek:utput method="text" />
<xsl:template match="/">
<xsl:apply-templates select="//z" />
</xsl:template>
<xsl:template match="z">
<xsl:for-each select="x">
<xsl:if test="position() mod 2 = 1">
[<xsl:value-of select="y" />]
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
[/blue][/tt]
You can have a further selection on z making it nowhere appearing //z and //x.
[tt][green]
<?xml version="1.0"?>
<!-- q ref -->
<xsl:stylesheet version="1.0" xmlns:xsl="<xsl:eek:utput method="text" />
<xsl:template match="/">
<xsl:apply-templates select="z[position() = 1]" />
</xsl:template>
<xsl:template match="z">
<xsl:for-each select="x">
<xsl:if test="position() mod 2 = 1">
[<xsl:value-of select="y" />]
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
[/green][/tt]
It all depends what you do and how thing structures. Any absolute precept is going to have very restricted utility. In particular, in the area of xslt, the goal and the path to get there is a one-to-many relation.
 
I don't really understand what point you are trying to make. These are not good examples of where to use //.

In your second example, why not use:
Code:
<xsl:apply-templates select="root/z" />
When you know the structure of the XML you are transforming, specify the path to aid the parser and the human reader.

Jon

"I don't regret this, but I both rue and lament it.
 
The point I am trying to make is that your blanket statement on // is wrong. But, as it is a matter of opinion, I just register that it is not that universally a good precept as it sounds and as you put it. As to the precision of the location-path, well, thing sounds in fact quite banality.
 
I didn't say never use //. There is a time and place for it, but it is rare. When using a node-set, you can almost always specify the full path.

Its not a matter of opinion, its a hard fact that // is vastly less efficient. I once brought down the transform time of a v large XML file from 5 mins to 30 secs just by replacing the // with full paths.

Jon

"I don't regret this, but I both rue and lament it.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top