XSLT和表:设置一行中的单元格数

时间:2011-03-22 05:17:37

标签: xslt

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>

我一直在尝试的XSL:

<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>

我想要的结果:

<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>  

我很尴尬地说我在这方面工作了多久。可以说蛮力,尝试一切多次技术都没有用。

2 个答案:

答案 0 :(得分:1)

更短且正确的解决方案

<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>

在提供的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>

产生了想要的正确结果

<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>

答案 1 :(得分:0)

每行渲染2个单元格。

从第一个节点开始选择每个第二个节点。对于这些,渲染包含self和以下单元格的行。如果最后一行不包含2个each元素,请使用空单元格完成该行。

<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>