【问题标题】:Mimic pivot table using XSLT 1.0使用 XSLT 1.0 模拟数据透视表
【发布时间】:2019-04-27 00:41:17
【问题描述】:

我想要一个显示以下 XML 的数据透视表。

<Records reportTime24h="18:02" reportTime="06:02:56PM" reportDate="2018-11-24" reportTitle="Pivot table">
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>F</Sex>
<TestID>1001</TestID>
<TestName>TRIGLYCERIDEN(501)</TestName>
<Total>91</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>F</Sex>
<TestID>1003</TestID>
<TestName>UREUM(501)</TestName>
<Total>62</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>M</Sex>
<TestID>1003</TestID>
<TestName>UREUM(501)</TestName>
<Total>1642</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>F</Sex>
<TestID>1004</TestID>
<TestName>NATRIUM(501)</TestName>
<Total>72</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>M</Sex>
<TestID>1004</TestID>
<TestName>NATRIUM(501)</TestName>
<Total>1929</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>F</Sex>
<TestID>1005</TestID>
<TestName>KALIUM(501)</TestName>
<Total>72</Total>
</Record>
<Record>
<Year>2017</Year>
<Month>11</Month>
<Sex>M</Sex>
<TestID>1005</TestID>
<TestName>KALIUM(501)</TestName>
<Total>1929</Total>
</Record>
</Records>

这是表格的外观。

行和列的交叉点应该是相交数据对应的Total xml节点。

这可能吗?

PD:我尝试使用 muenchian 分组来做到这一点。但是,我无法有效地跨列迭代数据。例如,该逻辑无法处理只有一种性别数据的节点。我尝试检查节点中的数据以显示零 (0),但失败了。

编辑

遵循评论者的建议。

这是我处理的 XSL 文件。它实现了预期的结果,但是当测试只有一种性别的数据时它会失败。它会将数据放在第一列,而不管数据是否属于列(性别)。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:key name="key-tests" match="Record" use="TestID" />
<xsl:key name="key-sex" match="Record" use="Sex" />

<xsl:key name="key-tests-sex" match="Record" use="concat(TestID,'::',Sex)" />

<xsl:template match="/Records">

<html>

    <head>

        <style>

            body        { font-family: monospace;                                       }
            table       { border-collapse: collapse; font-size: 8pt;                    }
            table thead { background-color: gainsboro; font-weight: bold;               }
            td,th       { border: 1px solid gainsboro; padding: 3px; min-width: 26px;   }
            tbody td    { text-align: right;                                    }

        </style>

    </head>

    <body>

        <table>

            <thead>
                <tr>
                    <th>Sex</th>
                    <xsl:apply-templates select="Record[generate-id() = generate-id(key('key-sex',Sex)[1])]" mode="key-sex"/>
                </tr>
            </thead>

            <tbody>
              <xsl:apply-templates select="Record[generate-id() = generate-id(key('key-tests',TestID)[1])]" mode="key-tests"/>
                <tr>
                    <th></th>
                    <th><xsl:value-of select="sum(key('key-sex','F')/Total)"/></th>
                    <th><xsl:value-of select="sum(key('key-sex','M')/Total)"/></th>
                </tr>
            </tbody>

        </table>       

    </body>

</html>

</xsl:template>
<!--Row Data (totals)-->
<xsl:template match="Record" mode="key-tests-sex">
    <td><xsl:value-of select="Total"/></td>
</xsl:template>

<!-- Doctors (HEADER ROW) -->
<xsl:template match="Record" mode="key-sex">
    <th><xsl:value-of select="Sex"/></th>
</xsl:template>

<!-- Tests (ROWS) -->
<xsl:template match="Record" mode="key-tests">
    <tr>
        <td><xsl:value-of select="TestName"/></td>
        <xsl:apply-templates select="key('key-tests',TestID)[generate-id() = generate-id(key('key-tests-sex',concat(TestID,'::',Sex))[1])]" mode="key-tests-sex"/>
    </tr>

</xsl:template>

</xsl:stylesheet>

这是最终结果图像。我只包括了在视口中可见的部分。它大约有 3 页长。但应该足以了解我要完成的工作。

图片有​​什么问题

女性 (7) 显示的计数实际上是男性的计数。

【问题讨论】:

  • XML 文件的数据和表的数据不匹配。在这种状态下,无法回答您的问题;即使您现在没有表现出任何自己的努力来解决这个问题。
  • 你好@zx485。谢谢回复。我包含的表格图像仅用于说明我希望实现的最终结果。它不应该与我包含的 XML 数据相匹配。此外,我在问题中复制的 XML 只是我正在使用的实际 XML 文件的一小部分。最后,请查看已编辑的问题,您将在其中找到: - 我使用的 XSL 文件,它几乎达到了预期的目标。 - 在应用 XSL 后,我包含了生成的 HTML 文件的图像

标签: xml xslt pivot-table xslt-1.0 muenchian-grouping


【解决方案1】:

尝试将模式key-tests匹配Record的模板更改为

<!-- Tests (ROWS) -->
<xsl:template match="Record" mode="key-tests">
    <tr>
        <td><xsl:value-of select="TestName"/></td>
        <td>
            <xsl:value-of select="key('key-tests',TestID)[generate-id() = generate-id(key('key-tests-sex',concat(TestID,'::','F'))[1])]/Total"/>
        </td>
        <td>
            <xsl:value-of select="key('key-tests',TestID)[generate-id() = generate-id(key('key-tests-sex',concat(TestID,'::','M'))[1])]/Total"/>
        </td>
    </tr>
</xsl:template>

这至少应该解决数字和性别关系错误的问题。

在您的真实数据中,Sex 元素的不同值不限于 F 和 M,您每次都需要一些方法来处理唯一值以创建 td 单元格,然后在里面映射到相关的Record 数据,这样模板就会变成

<!-- Tests (ROWS) -->
<xsl:template match="Record" mode="key-tests">
    <tr>
        <td><xsl:value-of select="TestName"/></td>
        <xsl:variable name="testId" select="TestID"/>
        <xsl:for-each select="$unique-genders">
            <td>
              <xsl:value-of select="key('key-tests', $testId)[generate-id() = generate-id(key('key-tests-sex',concat(TestID, '::', current()))[1])]/Total"/>  
            </td>
        </xsl:for-each>
    </tr>
</xsl:template>

带有声明

<xsl:key name="key-sex" match="Sex" use="." />

<xsl:variable name="unique-genders" select="//Sex[generate-id() = generate-id(key('key-sex', .)[1])]"/>

在https://xsltfiddle.liberty-development.net/3NzcBue/2中完成

【讨论】:

  • 感谢马丁的回复。这很有效,但是,我需要一种方法让模板自动适应性别的新条目(例如女性 - 怀孕)。所以传递给 Sex 的密钥无法修复。这可能吗?
  • 参见xsltfiddle.liberty-development.net/3NzcBue/2,我认为您希望每次都需要分别处理唯一的性别值以创建一个td,然后在内部映射到相关的Record 组(如果存在)。如果链接中的代码有帮助,我稍后会将其转化为答案。
  • Martin,是的,这看起来正是我所需要的。你是救生员。我会尽快尝试。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-12
相关资源
最近更新 更多