【问题标题】:XSLT XML to HTML Crosstab tableXSLT XML 到 HTML 交叉表
【发布时间】:2012-10-16 14:34:14
【问题描述】:

我正在尝试从 ToDoList (http://www.abstractspoon.com/tdl_resources.html) 中的 XML 文件创建一个交叉表这是一个示例 XML 文件:

<?xml version="1.0" encoding="utf-16" ?>
<TODOLIST PROJECTNAME="Projects">
    <TASK TITLE="proj1" ID="1" NUMPERSON="1" PERSON="Chris" NUMTAGS="1" TAG="Caro" CALCTIMEESTIMATE="36"/>
    <TASK TITLE="proj2" ID="2" NUMPERSON="1" PERSON="Chris" NUMTAGS="1" TAG="Nat" CALCTIMEESTIMATE="8" />
    <TASK TITLE="proj4" ID="4" NUMPERSON="1" PERSON="Chris" NUMTAGS="1" TAG="Caro" CALCTIMEESTIMATE="36" />
    <TASK TITLE="proj5" ID="5" NUMPERSON="1" PERSON="Sahb" NUMTAGS="1" TAG="Nat" CALCTIMEESTIMATE="128" />
    <TASK TITLE="proj32" ID="32" NUMPERSON="2" PERSON="Seb" PERSON1="Chris" NUMTAGS="1" TAG="Nat" CALCTIMEESTIMATE="0.90" />
</TODOLIST>

每个任务都是一个元素,所有信息都是属性。我想制作一个这样的表格,标签作为第一行,人员作为第一列。

<table>
    <tr>
        <td></td>
        <td>Caro</td>
        <td>Nat</td>
    </tr>
    <tr>
        <td>Chris</td>
        <td>72</td>
        <td>8</td>
    </tr>
    <tr>
        <td>Sahb</td>
        <td>128</td>
        <td>0</td>
    </tr>
    <tr>
        <td>Seb, Chris</td>
        <td>0</td>
        <td>9</td>
    </tr>
</table>

如您所见,同一个人可以有多个项目,我想根据标签为每个人添加 CALCTIMEESTIMATE。我可以得到第一行

<xsl:key name="dtag" match="/TODOLIST/TASK/@TAG" use="." />
<xsl:for-each select="TASK/@TAG[generate-id() = generate-id(key('dtag', .)[1])]">
    <td>
      <xsl:value-of select="."/>
    </td>
</xsl:for-each>

但是 sum 函数并没有给出想要的结果。我错过了什么?有没有一种简单的方法可以根据两个属性进行求和? ToDoList 使用 XSLT 1.0,这就是为什么我不能使用 distinct-values。

这是完整的 XSLT,我尝试了很多不同的东西,在这里我试图让它只为 Chris 工作,但它不会加起来他的 2 个项目。

<xsl:template match="TODOLIST">
<xsl:text disable-output-escaping="yes">&lt;!DOCTYPE html&gt;</xsl:text>
<html>
<head>
<title>Projects..</title>
</head>
<body>
<table>
<caption>Projects..</caption>
<thead>
<tr>
<td></td>

<xsl:for-each select="TASK/@TAG[generate-id() = generate-id(key('dtag', .)[1])]">
    <th scope="col">
      <xsl:value-of select="."/>
    </th>
</xsl:for-each>

</tr>
</thead>
<tbody>
<xsl:apply-templates select="TASK/@PERSON[generate-id() = generate-id(key('dperson', .)[1])]" />
</tbody>
</table>
</body>
</html>
</xsl:template>

<xsl:template match="TASK/@PERSON">
    <tr>
        <th scope="row">
          <xsl:value-of select="."/>
        </th>
        <xsl:apply-templates select="/TODOLIST/TASK/@TAG[generate-id() = generate-id(key('dtag', .)[1])]" />
    </tr>
</xsl:template>

<xsl:template match="/TODOLIST/TASK/@TAG">
    <td>
        <xsl:value-of select="sum(../@CALCTIMEESTIMATE[../@PERSON = 'Chris'])" />
    </td>
</xsl:template>

【问题讨论】:

  • 是否可以显示您正在使用的完整 XSLT,尤其是您提到的 sum 函数没有给出预期的结果?谢谢!
  • 我添加了我的 XSLT 模板。起初我没有模板,但我尝试了很多不同的东西。感谢收看。

标签: html xslt crosstab


【解决方案1】:

要使总和生效,您需要知道当前人员和当前标签。

在您当前匹配 TASK/@PERSON 的模板中,您应该将属性的当前值传递给下一个模板

<xsl:apply-templates 
   select="/TODOLIST/TASK/@TAG[generate-id() = generate-id(key('dtag', .)[1])]">
     <xsl:with-param name="PERSON" select="." />
</xsl:apply-templates>

然后,在匹配 @TAG 的模板中,您可以访问 SUM 中的 'dperson' 键,因此您可以汇总该人员和当前标签的所有任务,如下所示:

<xsl:template match="/TODOLIST/TASK/@TAG">
  <xsl:param name="PERSON" />
  <td>
    <xsl:value-of 
      select="sum(key('dperson', $PERSON)[../@TAG = current()]/../@CALCTIMEESTIMATE)"/>
  </td>
</xsl:template>

【讨论】:

  • 谢谢!这很好用!我知道这与钥匙有关。当有两个人时,我仍然需要弄清楚如何求和:Seb,Chris。以后我会尝试更多。再次感谢您。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-03
  • 1970-01-01
  • 2014-05-27
  • 1970-01-01
  • 2023-03-26
相关资源
最近更新 更多