如何在xslt中使用xsl:for-each
从xml文件中迭代获取值,并在表格中显示它
例如:xml文件就像
<order>
<item name ="a"/>
<item name ="b"/>
<item name ="c"/>
<item name ="d"/>
<item name ="e"/>
<item name ="f"/>
<item name ="g"/>
</order>
,输出应为
a b c d
e f g
循环应该对项目进行计数,如果它可以被4分割
应关闭当前行并添加新行等等..
我正在使用以下xslt
但我无法以表格格式显示
<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>
请帮我做这个
提前致谢
答案 0 :(得分:8)
在XSLT中考虑任何复杂问题的方法不是“如果将X作为输入,我将如何编写一个程序来生成Y?”但是,“给定输出Y,我将改变生产它的X?”掌握(或清晰表达)并不是一个简单的原则,但是一旦你得到它,XSLT中的难题似乎变得微不足道。
如果输出是一系列tr
元素,如下所示:
<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>
实质上有四个输出元素。所以必须有四个输入元素。
第一个问题是,哪四个?非常清楚,它将是第1,第4,第7和第10 - 也就是说,每3个元素,从第一个开始。所以你的出发点是转换这四个元素:
<xsl:apply-templates select="/order/item[position() mod 3 = 1]"/>
好的,现在我们已经选择了每个第三个元素,我们如何创建一个tr
以及它之后的元素?使用following-sibling
轴:
<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>
就目前而言,这很好。但是有相当数量的重复代码,如果你想(比如说)将列数从3改为6,你必须修改很多。你可以通过制作另一个模板来消除重复的代码:
<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>
你可以通过将列放在一个变量中来参数化列数,就像Dimitre在他的例子中所做的那样。
答案 1 :(得分:7)
此转化:
<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>
应用于提供的XML文档时,会生成所需的正确结果:
<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>
答案 2 :(得分:-1)
我不是100%肯定,但下面的代码应该这样做:
<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>
答案 3 :(得分:-4)
<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>