尝试使用XSLT从XML创建HTML表

尝试使用XSLT从XML创建HTML表,xml,xslt,xslt-1.0,xslt-2.0,xslt-grouping,Xml,Xslt,Xslt 1.0,Xslt 2.0,Xslt Grouping,我正在努力使用XSLT。我被困在程序性的土地上。 基本上,我有一些XML是从一个看起来有点像这样的数据库生成的: <?xml version="1.0" encoding="iso-8859-1"?> <report> <generated_dtm>2013-03-08T18:57:26+00:00</generated_dtm> <range> <start_dtm>2013-02-21T

我正在努力使用XSLT。我被困在程序性的土地上。 基本上,我有一些XML是从一个看起来有点像这样的数据库生成的:

<?xml version="1.0" encoding="iso-8859-1"?>
<report>
    <generated_dtm>2013-03-08T18:57:26+00:00</generated_dtm>

    <range>
        <start_dtm>2013-02-21T17:52:00+00:00</start_dtm>
        <end_dtm>2013-03-08T17:52:00+00:00</end_dtm>
    </range>

    <sensor site_code="A0001" unit_no="1" sensor_no="1">
        <name>Food</name>
        <mu_symbol>°C</mu_symbol>
    </sensor>

    <sensor site_code="A0001" unit_no="1" sensor_no="2">
        <name>Air</name>
        <mu_symbol>°C</mu_symbol>
    </sensor>

    <readings>
        <slot slot_dtm="2013-02-21T17:50:00+00:00">
            <sensor sensor_no="1">
                <v>10</v>
                <status_code>IR</status_code>
                <status_desc>In Range</status_desc>
            </sensor>
            <sensor sensor_no="2">
                <v>20</v>
                <status_code>Lo</status_code>
                <status_desc>Low</status_desc>
                </sensor>
        </slot>

        <slot slot_dtm="2013-02-21T18:00:00+00:00">
            <sensor sensor_no="2">
                <v>21</v>
                <status_code>Lo</status_code>
                <status_desc>Low</status_desc>
            </sensor>
            <sensor sensor_no="1">
                <v>11</v>
                <status_code>IR</status_code>
                <status_desc>In Range</status_desc>
            </sensor>
        </slot>
    </readings>
</report>
Time                      | Food | Air
-------------------------------------
2013-02-21T17:50:00+00:00 | 10   | 11
2013-02-21T18:00:00+00:00 | 20   | 22
<readings>
    <slot slot_dtm="2013-02-21T17:50:00+00:00">
        <sensor sensor_no="1">
            <v>10</v>
            <status_code>IR</status_code>
            <status_desc>In Range</status_desc>
        </sensor>
    </slot>

    <slot slot_dtm="2013-02-21T17:50:00+00:00">
        <sensor sensor_no="2">
            <v>20</v>
            <status_code>Lo</status_code>
            <status_desc>Low</status_desc>
            </sensor>
    </slot>

    <slot slot_dtm="2013-02-21T18:00:00+00:00">
        <sensor sensor_no="1">
            <v>11</v>
            <status_code>IR</status_code>
            <status_desc>In Range</status_desc>
        </sensor>
    </slot>

    <slot slot_dtm="2013-02-21T18:00:00+00:00">
        <sensor sensor_no="2">
            <v>21</v>
            <status_code>Lo</status_code>
            <status_desc>Low</status_desc>
        </sensor>
    </slot>
</readings>
虽然时隙的顺序保证是递增的,所以我不需要对它们进行排序(可能有1000个),但问题是在每个时隙内,传感器的顺序无法保证,所以我想我会循环遍历每次用来创建表头的传感器,并在遍历这些插槽时从每个插槽中选择正确的传感器。虽然这不起作用,但你可能会得到我尝试过的结果(我现在意识到为什么它不起作用..变量的行为与我预期的不一样!):-


报告
时间
可能有100个甚至1000个时隙,这只是一个小例子。 如果有帮助的话,我可以调整XML的层次结构,但是如果不对数据库查询进行一些认真的修改,我无法在每个时间段内将传感器按顺序排列。我希望这不是必要的

最初我使用XML,其中插槽是这样分开的:

<?xml version="1.0" encoding="iso-8859-1"?>
<report>
    <generated_dtm>2013-03-08T18:57:26+00:00</generated_dtm>

    <range>
        <start_dtm>2013-02-21T17:52:00+00:00</start_dtm>
        <end_dtm>2013-03-08T17:52:00+00:00</end_dtm>
    </range>

    <sensor site_code="A0001" unit_no="1" sensor_no="1">
        <name>Food</name>
        <mu_symbol>°C</mu_symbol>
    </sensor>

    <sensor site_code="A0001" unit_no="1" sensor_no="2">
        <name>Air</name>
        <mu_symbol>°C</mu_symbol>
    </sensor>

    <readings>
        <slot slot_dtm="2013-02-21T17:50:00+00:00">
            <sensor sensor_no="1">
                <v>10</v>
                <status_code>IR</status_code>
                <status_desc>In Range</status_desc>
            </sensor>
            <sensor sensor_no="2">
                <v>20</v>
                <status_code>Lo</status_code>
                <status_desc>Low</status_desc>
                </sensor>
        </slot>

        <slot slot_dtm="2013-02-21T18:00:00+00:00">
            <sensor sensor_no="2">
                <v>21</v>
                <status_code>Lo</status_code>
                <status_desc>Low</status_desc>
            </sensor>
            <sensor sensor_no="1">
                <v>11</v>
                <status_code>IR</status_code>
                <status_desc>In Range</status_desc>
            </sensor>
        </slot>
    </readings>
</report>
Time                      | Food | Air
-------------------------------------
2013-02-21T17:50:00+00:00 | 10   | 11
2013-02-21T18:00:00+00:00 | 20   | 22
<readings>
    <slot slot_dtm="2013-02-21T17:50:00+00:00">
        <sensor sensor_no="1">
            <v>10</v>
            <status_code>IR</status_code>
            <status_desc>In Range</status_desc>
        </sensor>
    </slot>

    <slot slot_dtm="2013-02-21T17:50:00+00:00">
        <sensor sensor_no="2">
            <v>20</v>
            <status_code>Lo</status_code>
            <status_desc>Low</status_desc>
            </sensor>
    </slot>

    <slot slot_dtm="2013-02-21T18:00:00+00:00">
        <sensor sensor_no="1">
            <v>11</v>
            <status_code>IR</status_code>
            <status_desc>In Range</status_desc>
        </sensor>
    </slot>

    <slot slot_dtm="2013-02-21T18:00:00+00:00">
        <sensor sensor_no="2">
            <v>21</v>
            <status_code>Lo</status_code>
            <status_desc>Low</status_desc>
        </sensor>
    </slot>
</readings>

10
红外光谱
射程内
20
瞧
低
11
红外光谱
射程内
21
瞧
低
这涉及到一个更简单的数据库查询!在这里,我可以保证顺序,但我使用的XQuery处理器(Qt的QXmlQuery)不支持每个组,因此我无法找到基于时间的分组方法

对不起,时间太长了,我希望有人能帮我找到正确的方向

谢谢。

这应该可以做到:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:variable name="allSensors" select="/report/sensor" />

  <xsl:template match="report">
    <html>
      <head>
        <title>Report</title>
      </head>
      <body>
        <table border="0" width="100%" bgcolor="#ffffff"
               cellspacing="0" cellpadding="2">
          <tr>
            <td class="column_head_above" width="70">Time</td>
            <xsl:apply-templates select="sensor" />
          </tr>
          <xsl:apply-templates select="readings/slot" />
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="report/sensor">
    <td class="column_head_above">
      <xsl:value-of select="concat(name, ' ', mu_symbol)"/>
    </td>
  </xsl:template>

  <xsl:template match="slot">
    <xsl:variable name="currentSensors" select="sensor" />
    <tr>
      <td class="table_data">
        <xsl:value-of select="@slot_dtm"/>
      </td>

      <xsl:apply-templates select="$allSensors/@sensor_no">
        <xsl:with-param name="currentSlot" select="current()/@slot_dtm" />
      </xsl:apply-templates>
    </tr>
  </xsl:template>

  <xsl:template match="@sensor_no">
    <xsl:param name="currentSlot" />

    <td>
      <xsl:variable name="matchingSensor"
                    select="/report/readings/slot[@slot_dtm = $currentSlot]
                            /sensor[@sensor_no = current()]" />
      <xsl:value-of select="concat($matchingSensor/v, ' - ', 
                                       $matchingSensor/status_desc)" />
    </td>
  </xsl:template>
</xsl:stylesheet>

在花了一些时间弄清楚之后,这里有一个更新。感谢杰里什的回答。在这一点和我的计算结果之间,它开始变得清晰起来(直到下一个问题)


报告
时间
-
-

谢谢!自从写了这个问题,我已经开始有所进展了,而且离你上面提到的不远了。我想在仔细看了你所说的之后,它会被点击的。我会把我得到的作为一个单独的答案,但我会把你的答案标记为正确答案。再次感谢:-)问题:我已经根据您的代码更新了我的版本,但它实际上不起作用。这可能与我使用的XSLT处理器有关(这是Qt4.8.4中的处理器,我认为它使用libxml2),但基本上只要我进入for-each循环,$currentSensors就会变为空,好像它不存在一样。这基本上是我必须首先解决的问题,即只要我为每个循环输入一个值,前面范围中的任何内容似乎都不存在。有什么想法吗?嗯,这很奇怪。你能试试上面的修改吗?我为
td
s创建了一个单独的模板,并将
$currentSensors
作为参数传递。我想知道在这种情况下该变量是否仍然会被忽略。我得到了以下错误:必需的类型是node(),但找到了item()。它看起来像是Qt 4.8 XSLT处理器。如果我使用xsltproc(随libxslt一起提供),它可以正常工作——如果我在软件中使用libxml和libxslt,它也可以正常工作。这只是一种痛苦,因为它意味着更多的依赖关系,但看起来我必须停止使用Qt进行XSLT处理。这种方法的一个限制是,如果任何
元素缺少
,则可能会缺少
(我不知道在您的情况下是否会发生这种情况)。如果ID总是数字的,我建议将
data type=“numeric”
添加到
xsl:sort
s。