asdasdas
asdasdas

Reputation: 301

xml and xsl cannot loop

I have an XML:

<service>
     <row>
          <column>service1</column>
          <column>service2</column>
          <column>service3</column>
     </row>
</service>

I want to loop all the service1 to service3. In XSL I used:

<xsl:for-each select="service/row">
    <fo:block>
         <xsl:value-of select="column" />
    </fo:block>
</xsl:for-each>

How come it will only output the first column which is "column1"? how do you loop from service1 to service3? I just followed the tutorial in w3schools but cant replicate using this example. What did I miss? I'm just new to XSL and XML.

Upvotes: 1

Views: 53

Answers (2)

Tomalak
Tomalak

Reputation: 338336

You see only the first value because <xsl:value-of> outputs the string value of its argument.

And the string value of a set of nodes is the text content of the first node - that's how node-sets are converted to string by definition.

Bottom line, you're doing it wrong.


<xsl:for-each select="service/row">
  <fo:block>
    <xsl:for-each select="column" />
      <fo:block>
        <xsl:value-of select="." />
      </fo:block>
    </xsl:for-each>
  </fo:block>
</xsl:for-each>

But in reality you shouldn't use <xsl:for-each> for things that. Use template matching and <xsl:apply-templates>, for example like this:

<!-- <service> becomes a table -->
<xsl:for-each select="service">
  <fo:table>
    <xsl:apply-templates />
  </fo:table>
</xsl:for-each>

<!-- <row> becomes a table-row -->
<xsl:template match="service/row">
  <fo:table-row>
    <xsl:apply-templates />
  </fo:table-row>
</xsl:template>

<!-- <column> becomes a table-cell -->
<xsl:template match="service/row/column">
  <fo:table-cell>
    <xsl:value-of select="." />
  </fo:table-cell>
</xsl:template>

Upvotes: 1

John Wickerson
John Wickerson

Reputation: 1232

Think in terms of a file-system. Your for-each loop is looping over each row directory in the service directory, and printing the value of that row's column. Each row has several columns, but value-of will only give you the first. You have only one row, so you get only one column.

What you want to do is loop over each column directory in each row in each service. Then you print the value of the current "directory", which, like in Unix, is obtained using the . symbol. So, adjust your code like this

<xsl:for-each select="service/row/column">
    <fo:block>
         <xsl:value-of select="." />
    </fo:block>
</xsl:for-each>

and it should all work fine!

Upvotes: 1

Related Questions