The XML:
<data>
<table id="returns">
<each>
<name>1 year</name>
<value>17.01062531999216</value>
</each>
<each>
<name>3 years</name>
<value>18.01062531999216</value>
</each>
<each>
<name>5 years</name>
<value>21.01062531999216</value>
</each>
<each>
<name>Since inception</name>
<value>12.01062531999216</value>
</each>
</table>
</data>
The XSL I have been trying:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<tr>
<xsl:for-each select="data/table[@id='returns']/each">
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="value"/></td>
<xsl:if test="//each[position() mod 2 = 0]">
<xsl:text disable-output-escaping="yes"></tr><tr></xsl:text>
</xsl:if>
</xsl:for-each>
</tr>
</xsl:template>
</xsl:stylesheet>
The result I want:
<table>
<tr>
<td>1 year</td>
<td>17.01062531999216</td>
<td>3 years</td>
<td>18.01062531999216</td>
</tr>
<tr>
<td>5 years</td>
&l开发者_如何学Ct;td>21.01062531999216</td>
<td>Since inception</td>
<td>12.01062531999216</td>
</tr>
</table>
I'm embarrassed to say how long I have been working on this. Suffice to say the brute force, try-everything-multiple-times technique didn't work.
A shorter and correct solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="table">
<table>
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template match="each[position() mod 2 = 1]">
<tr>
<xsl:apply-templates select="(.|following-sibling::each[1])/*"/>
</tr>
</xsl:template>
<xsl:template match="name|value">
<td><xsl:apply-templates/></td>
</xsl:template>
<xsl:template match="each[position() mod 2 = 0]"/>
</xsl:stylesheet>
when this transformation is applied on the provided XML document:
<data>
<table id="returns">
<each>
<name>1 year</name>
<value>17.01062531999216</value>
</each>
<each>
<name>3 years</name>
<value>18.01062531999216</value>
</each>
<each>
<name>5 years</name>
<value>21.01062531999216</value>
</each>
<each>
<name>Since inception</name>
<value>12.01062531999216</value>
</each>
</table>
</data>
the wanted, correct result is produced:
<table>
<tr>
<td>1 year</td>
<td>17.01062531999216</td>
<td>3 years</td>
<td>18.01062531999216</td>
</tr>
<tr>
<td>5 years</td>
<td>21.01062531999216</td>
<td>Since inception</td>
<td>12.01062531999216</td>
</tr>
</table>
To render 2 cells per row.
Select every second node starting with the first. For these, render a row containing self and the following cell. If the last row does not contain 2 each
elements, finish the row with empty cells.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="table">
<table>
<xsl:apply-templates select="each[1 = position() mod 2]"/>
</table>
</xsl:template>
<xsl:template match="each">
<tr>
<xsl:for-each select=". | following-sibling::each[1]" >
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="value"/></td>
</xsl:for-each>
<xsl:if test="not(following-sibling::each)">
<td/>
<td/>
</xsl:if>
</tr>
</xsl:template>
</xsl:stylesheet>
精彩评论