首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试使用XSLT从XML创建HTML表

尝试使用XSLT从XML创建HTML表
EN

Stack Overflow用户
提问于 2013-03-09 03:55:04
回答 2查看 2.3K关注 0票数 0

我正在努力使用XSLT。我陷入了程序化的境地。基本上,我有一些从数据库生成的XML,看起来有点像这样:

代码语言:javascript
复制
<?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>

我试图以HTML表中的读数结束,每个传感器都是一列,每行的时间都在左侧,如下所示:

代码语言:javascript
复制
Time                      | Food | Air
-------------------------------------
2013-02-21T17:50:00+00:00 | 10   | 11
2013-02-21T18:00:00+00:00 | 20   | 22

虽然时隙的顺序保证是升序的,所以我不需要对它们进行排序(可能有1000个),但问题是在每个时隙内传感器的顺序不能得到保证,所以我想我应该循环遍历每次用于创建表头的传感器,并在遍历这些时隙时从每个时隙中选择正确的传感器。虽然这不起作用,但你可能会明白我想要做的事情(我现在明白为什么它不起作用了。变量的行为不符合我的预期!):-

代码语言:javascript
复制
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<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:for-each select="sensor">
            <td class="column_head_above"><xsl:value-of select="name"/><xsl:text> </xsl:text><xsl:value-of select="mu_symbol"/></td>
          </xsl:for-each>
        </tr>

        <!-- go through each time slot -->

        <xsl:for-each select="readings/slot">
          <tr>
            <xsl:variable name="sdtm" select="@slot_dtm" /> 

            <td class="table_data"><xsl:value-of select="$sdtm"/></td>

            <!-- go through each sensor header -->

            <xsl:for-each select="../sensor">
              <xsl:variable name="sno" select="@sensor_no" /> 
              <td>
                <xsl:value-of select="../readings/slot[@slot_dtm=$sdtm]/sensor[@sensor_no=$sno]/v"/>
                <xsl:value-of select="../readings/slot[@slot_dtm=$sdtm]/sensor[@sensor_no=$sno]/status_desc"/>
              </td>
            </xsl:for-each>

          </tr>
        </xsl:for-each>

        <!-- end: go through each time slot -->

      </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

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

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

代码语言:javascript
复制
<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>

这涉及到一个简单得多的数据库查询!这里我可以保证顺序,但是我正在使用的XQuery处理器(Qt的QXmlQuery)不支持每个组,所以我找不到一种基于时间的分组方法。

很抱歉,这篇文章太长了,我希望至少有人能帮我指出正确的方向。

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-03-09 04:51:01

这应该可以做到:

代码语言:javascript
复制
<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>

我在这里做了一些清理,但要点是:

为了简单起见,

  • 保留了对传感器定义的变量引用当前插槽的传感器的变量引用,可以在for-each.

中引用

当在你的样本输入上运行时,这会产生:

代码语言:javascript
复制
<html>
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <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>
        <td class="column_head_above">Food °C</td>
        <td class="column_head_above">Air °C</td>
      </tr>
      <tr>
        <td class="table_data">2013-02-21T17:50:00+00:00</td>
        <td>10 - In Range</td>
        <td>20 - Low</td>
      </tr>
      <tr>
        <td class="table_data">2013-02-21T18:00:00+00:00</td>
        <td>11 - In Range</td>
        <td>21 - Low</td>
      </tr>
    </table>
  </body>
</html>
票数 1
EN

Stack Overflow用户

发布于 2013-03-09 05:01:27

这是在花了一些时间弄清楚之后的更新。也感谢JLRishe的回答。在这和我所做的工作之间,它开始变得清晰起来(直到下一个问题!)。

代码语言:javascript
复制
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<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="sensors/sensor">
            <xsl:sort select="@sensor_no" />
          </xsl:apply-templates>
        </tr>

        <!-- go through each time slot -->

        <xsl:for-each select="readings/slot">
          <tr>
            <td class="table_data"><xsl:value-of select="@slot_dtm"/></td>

            <!-- go through each sensor header -->

            <xsl:apply-templates select="sensor">
              <xsl:sort select="@sensor_no" />
            </xsl:apply-templates>

          </tr>
        </xsl:for-each>

        <!-- end: go through each time slot -->

      </table>
  </body>
  </html>
</xsl:template>

<xsl:template match="slot/sensor">
    <td>
        <xsl:value-of select="@sensor_no"/> -
        <xsl:value-of select="v"/> -
        <xsl:value-of select="status_desc"/>
    </td>
</xsl:template>

<xsl:template match="sensors/sensor">
    <td class="column_head_above">
        <xsl:value-of select="name"/><xsl:text> </xsl:text><xsl:value-of select="mu_symbol"/>
    </td>
</xsl:template>

</xsl:stylesheet>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15302199

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档