开发者

XSLT and tables: setting number of cells in a row

开发者 https://www.devze.com 2023-02-18 02:50 出处:网络
The XML: <data> <table id=\"returns\"> <each> <name>1 year</name> <value>17.01062531999216</value>

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

精彩评论

暂无评论...
验证码 换一张
取 消