Hladeo
Hladeo

Reputation: 577

xsl for each iterates only once

Simplified structure of my XML:

<CV>
  <info>
    <firstname>Sam</firstname>
    <lastname>Smith</lastname>
    <birthday>19/08/1978</birthday>
  </info>

  <additions>
    <name>japan language course</name>
    <name>skipper course</name>
  </additions>

  <interests>
    <name>cycling</name>
    <name>runing</name>
    <name>surfing</name>
  </interests>
</CV>

I've got a problem with iteratations using xsl for-each on additions and interests:

<xsl:for-each select="/CV/additions">
  <xsl:value-of select="name"/>
</xsl:for-each>

It shows me only "japan language course" and "cycling".

Is it possible that the structure is incorrect? The easiest way to solve my problem is to change:

  <interests>
    <name>cycling</name>
    <name>runing</name>
    <name>surfing</name>
  </interests>

into:

  <interests>
    <interest>
      <name>cycling</name>
    </interest>
    <interest>
      <name>runing</name>
    </interest>
    <interest>
      <name>surfing</name>
    </interest>
  </interests>

but I think it's quite stupid to create sub-childs...

Regards

Upvotes: 0

Views: 2085

Answers (3)

Michael Kay
Michael Kay

Reputation: 163322

The other part of the explanation is purely psychological. The word "additions" in English is a plural noun, so you were misled into thinking that when you select it, you are selecting several things. I feel sure that if the element had been named "addition", you would not have made this mistake.

Upvotes: -1

JLRishe
JLRishe

Reputation: 101680

You've found the solution, but as far as the explanation goes...

xsl:for-each iterates through all of the nodes selected by an XPath. In your initial attempt, the path /CV/additions only matched one node, so it only iterated once. In your solution, you used the path /CV/additions/name which selects all three name elements and iterates through them.

It's worth noting that use of xsl:for-each is often discouraged, in favor of templates, though the treatment of paths here works on the same principle:

<xsl:template match="/">
  <xsl:apply-templates select="/CV/additions/name" />
  <xsl:apply-templates select="/CV/interests/name" />
</xsl:template>

<xsl:template match="additions/name">
  <xsl:value-of select="concat('Addition: ', ., '&#xA;')" />
</xsl:template>

<xsl:template match="interests/name">
  <xsl:value-of select="concat('Interest: ', ., '&#xA;')" />
</xsl:template>

Upvotes: 1

Hladeo
Hladeo

Reputation: 577

Found the solution by trial and error:

<xsl:for-each select="/CV/additions/name">
  <xsl:value-of select="."/>
</xsl:for-each>

Upvotes: 0

Related Questions