XSL:如何改进这段代码?

时间:2013-07-23 06:52:43

标签: xml xslt

抱歉,我正在学习XSL,我想显示一个这样的表:

|   Param1    | Param2 |
-------+------+---------
| p1.1 | p1.2 |   p2   |
-------+------+---------
|  a11 |  a21 |   b01  |
|  a12 |  a22 |   b02  |

现在,我有一个xml:

 <?xml version="1.0" encoding="UTF-8"?>
 <tb>
    <col title="Param1">
        <row name="1">
        <stats name="p1.1" >a11</stats>
        <stats name="p1.2" >a12</stats>
        </row>
        <row name="2">
        <stats name="p1.1" >a21</stats>
        <stats name="p1.2" >a22</stats>
        </row>
    </col>
    <col title="Param2">
        <row name="1">
        <stats name="p2" >b01</stats>
        </row>
        <row name="2">
        <stats name="p2" >b02</stats>
        </row>
    </col>

和xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:for-each select="tb">
    <table class="data_table" style="width: 100%; background:gray">
        <thead>
          <tr>
         <xsl:for-each select="col">
            <xsl:choose>
            <xsl:when test="count(row[1]/stats) > 1">
                <th colspan="{count(row[1]/stats)}">
                    <xsl:value-of select="@title" />
                </th>
            </xsl:when>
            <xsl:otherwise>
                <th><xsl:value-of select="@title" /></th>
            </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </tr>
    <tr>
        <xsl:for-each select="col/row[1]/stats">
            <th><xsl:value-of select="@name" /></th>
        </xsl:for-each>
    </tr>
        </thead>
        <tbody>

           <tr>
                <xsl:for-each select="col/row[1]/stats">
                <td>
                    <xsl:value-of select="." />
                </td>
                </xsl:for-each>
              </tr>
              <tr>
                <xsl:for-each select="col/row[2]/stats">
                <td>
                <xsl:value-of select="." />
            </td>
                    </xsl:for-each>
          </tr>
        </tbody>
      </table>
   </xsl:for-each>

它有效,但如何使用单个FOR来组合表行来改进此代码?在示例中,我只有2行(a11 | a21 | b01和a12 | a22 | b02)和3列,但这可能会改变(20行,4列......)。也许我需要对属于同一行的单元格进行分组。

1 个答案:

答案 0 :(得分:4)

要改进XSLT,首先要做的就是使用模板。完成后,您可以执行以下操作以处理任意数量的行。

此解决方案假设源数据中的每个<col>对于您需要的每一行都有<row>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/tb">
    <table class="data_table" style="width: 100%; background:gray">
      <thead>
        <tr>
          <xsl:apply-templates select="col" mode="titles" />
        </tr>
        <tr>
          <xsl:apply-templates select="col/row[1]/stats" mode="titles" />
        </tr>
      </thead>
      <tbody>
        <xsl:apply-templates select="col[1]/row" />
      </tbody>
    </table>

  </xsl:template>

  <xsl:template match="col" mode="titles">
    <th>
      <xsl:apply-templates select="(.)[row[1]/stats[2]]" mode="colSpan" />
      <xsl:value-of select="@title"/>
    </th>
  </xsl:template>

  <xsl:template match="col" mode="colSpan">
    <xsl:attribute name="colspan">
      <xsl:value-of select="count(row[1]/stats)"/>
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="stats" mode="titles">
    <th>
      <xsl:value-of select="@name" />
    </th>
  </xsl:template>

  <xsl:template match="row">
    <tr>
      <xsl:apply-templates select="../../col/row[@name = current()/@name]/stats" /> 
    </tr>
  </xsl:template>

  <xsl:template match="stats">
    <td>
      <xsl:value-of select="." />
    </td>
  </xsl:template>
</xsl:stylesheet>

在样本输入上运行时,结果为:

<table class="data_table" style="width: 100%; background:gray">
  <thead>
    <tr>
      <th colspan="2">Param1</th>
      <th>Param2</th>
    </tr>
    <tr>
      <th>p1.1</th>
      <th>p1.2</th>
      <th>p2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>a11</td>
      <td>a12</td>
      <td>b01</td>
    </tr>
    <tr>
      <td>a21</td>
      <td>a22</td>
      <td>b02</td>
    </tr>
  </tbody>
</table>