How to use xsl:for-each
in xslt to get value iteratively from an xml file and to dispaly it in table fromat
For example: the xml file is like
<order>
<item name ="a"/>
<item name ="b"/>
<item name ="c"/>
<item name ="d"/>
&l开发者_如何学Ct;item name ="e"/>
<item name ="f"/>
<item name ="g"/>
</order>
and the output should be
a b c d
e f g
the loop should count the item and if it is divisble by 4 it
should close the current row and add a new row and so on..
i'm using the following xslt for this
but i can not display it in table format
<xsl:template match="/">
<html>
<body>
<xsl:call-template name ="incr">
<xsl:with-param name ="value">1</xsl:with-param>
<xsl:with-param name ="limit">
<xsl:value-of select ="count(//item)"/>
</xsl:with-param>
</xsl:call-template>
</body>
</html>
</xsl:template >
<xsl:template name="incr">
<xsl:param name="value"/>
<xsl:param name ="limit"/>
<xsl:if test ="$value!=$limit+1">
<xsl:value-of select ="//item[$value]/@name"/>
<xsl:if test ="$value mod 4 =0">
<br/>
<br/>
</xsl:if>
<xsl:call-template name ="incr">
<xsl:with-param name ="value" select ="$value+1"/>
<xsl:with-param name ="limit" select ="$limit"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
please help me to do this
Thanks in advance
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vNumCols" select="4"/>
<xsl:template match="/*">
<table>
<xsl:for-each select=
"item[position() mod $vNumCols = 1]">
<tr>
<xsl:for-each select=
". | following-sibling::*
[not(position() >= $vNumCols)]">
<td><xsl:value-of select="@name"/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document, produces the desired correct results:
<table>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
</tr>
<tr>
<td>e</td>
<td>f</td>
<td>g</td>
</tr>
</table>
The way to think about problems of any complexity in XSLT is not "how would I write a program to produce Y, given X as input?" but rather, "given output Y, what X am I going to transform to produce it?" It's not an easy principle to grasp (or articulate), but once you get it, what seem like hard problems in XSLT become trivial.
If the output is a series of tr
elements, like this:
<tr>
<td>a</td><td>b</td><td>c</td>
</tr>
<tr>
<td>d</td><td>e</td><td>f</td>
</tr>
<tr>
<td>g</td><td>h</td><td>i</td>
</tr>
<tr>
<td>j</td><td/><td/>
</tr>
there are, in essence, four output elements. So there must be four input elements.
The first question is, which four? Pretty clearly, it's going to be the 1st, 4th, 7th, and 10th - that is, every 3 elements, starting with the first. So your starting point is to transform those four elements:
<xsl:apply-templates select="/order/item[position() mod 3 = 1]"/>
Okay, and now that we've selected every third element, how are we going to create a tr
out of it and the elements right after it? Using the following-sibling
axis:
<xsl:template match="item">
<tr>
<td><xsl:value-of select="@name"/></td>
<td><xsl:value-of select="following-sibling::item[1]/@name"/></td>
<td><xsl:value-of select="following-sibling::item[2]/@name"/></td>
</tr>
</xsl:template>
That's good, as far as it goes. But there's a fair amount of duplicated code, and a lot you have to modify if you want (say) to change the number of columns from 3 to 6. You can eliminate the duplicated code by making another template:
<xsl:template match="item">
<tr>
<xsl:apply-templates select="@name | following-sibling::item[position() <= 3]/@name"/>
</tr>
</xsl:template>
<xsl:template match="@name">
<td><xsl:value-of select="."/></td>
</xsl:template>
And you can parameterize the number of columns by putting it in a variable, as Dimitre has done in his example.
I am not 100% sure but the code below should do it:
<table>
<tr>
<xsl:for-each select="//order/item">
<td>
<xsl:value-of select ="current()/@name"/>
</td>
<xsl:if test="position() mod 4 = 0">
<xsl:text disable-output-escaping="yes"><![CDATA[</tr><tr>]]></xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:variable name="item_count_mod4" select="count(//order/item) mod 4"/>
<xsl:choose>
<xsl:when test="$item_count_mod4 = 1">
<td></td><td></td><td></td>
</xsl:when>
<xsl:when test="$item_count_mod4 = 2">
<td></td><td></td>
</xsl:when>
<xsl:when test="$item_count_mod4 = 3">
<td></td>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</tr>
</table>
<table>
<tr>
<xsl:for-each select="//order/item">
<td>
<xsl:value-of select ="current()/@name"/>
</td>
<xsl:if test="position() mod 4 = 0">
<xsl:text disable-output-escaping="yes"><![CDATA[</tr><tr>]]></xsl:text>
</xsl:if>
</xsl:for-each>
</tr>
</table>
精彩评论