使用 XSLT 1.0 模拟枢轴 table
Mimic pivot table using XSLT 1.0
我想要一个将显示以下 XML.
的枢轴 table
<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>
table 应该是这样的。
行与列的交叉应该是交叉数据对应的Totalxml节点
这可能吗?
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) 实际上是男性人数。
尝试将模式 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])]"/>
相同
我想要一个将显示以下 XML.
的枢轴 table<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>
table 应该是这样的。
行与列的交叉应该是交叉数据对应的Totalxml节点
这可能吗?
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) 实际上是男性人数。
尝试将模式 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])]"/>
相同