XSLT:使用多个键制作网格
XSLT: Use multiple keys to make a grid
这是我上一个问题的后续问题。我从 Table 格式的网格开始:
A1,B1,C1
A2,B2,C2
A3,B3,C3
现在这个 table 结果根据记录中的实例值最多重复 5 次。对于 table.
的每个实例,单元格中的值将不同
我正在使用的 XML 为每条记录提供一个单元格值以及 DayOfWeek(列)、流(行)和实例(table 的迭代)值。
多亏了以前的帮助,我现在有了 XSLT,它可以让我创建一个网格(列 x 行)。但是,当我添加一个额外的键(逐行)以遍历实例时,XSLT 失败。
目标结果如下:
Instance 1
A1,B1,C1
A2, ,C2
A3,B3,C3
Instance 2
D1,E1,F1
D2, ,F2
D3,E3,F3
最多可以有 5 个实例,一周最多 7 天,行数任意。
更新
我已经根据 Michael 的贡献更新了 XSLT,但我仍然不在那里。当前结果为
A1 A1 A1 A1 B1 B1 B1 C1 C1 C1 C1
A2 A2 A2 A2 C2 C2 C2 C2
A3 A3 A3 A3 B3 B3 B3 C3 C3 C3 C3
A1 A1 A1 A1 B1 B1 B1 C1 C1 C1 C1
A2 A2 A2 A2 C2 C2 C2 C2
A3 A3 A3 A3 B3 B3 B3 C3 C3 C3 C3
我有两个 table 的迭代,但它们包含相同的数据,并且列重复次数太多!
XSL:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="row-by-instance" match="DataRow" use="Instance" />
<xsl:key name="row-by-stream" match="DataRow" use="concat(Instance, '|', Stream)" />
<xsl:key name="row-by-day" match="DataRow" use="concat(Instance, '|', Stream,'|',DayOfWeek)" />
<xsl:template match="/QueryResults">
<!-- a column for each distinct day of week -->
<xsl:variable name="columns" select="DataRow[generate-id() = generate-id(key('row-by-day',concat(Instance, '|', DayOfWeek))[1])]" />
<xsl:for-each select="DataRow[count(. | key('row-by-instance', Instance)[1]) = 1]">
<table border="1">
<!-- a row for each distinct stream -->
<!--<xsl:for-each select="DataRow[count(. | key('row-by-stream', Instance)[1]) = 1]">-->
<xsl:for-each select="key('row-by-instance', Instance)[count(. | key('row-by-stream', concat(Instance, '|', Stream))[1]) = 1]">
<xsl:variable name="stream" select="key('row-by-stream', concat(Instance, '|', Stream))" />
<tr>
<!-- a cell for each column -->
<xsl:for-each select="key('row-by-instance', Instance)[count(. | key('row-by-day', concat(Instance, '|', Stream,'|',DayOfWeek))[1]) = 1]">
<xsl:sort select="DayOfWeek" data-type="number" order="ascending"/>
<td>
<xsl:value-of select="$stream[DayOfWeek = current()/DayOfWeek]/DisplayStuff" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:for-each>
</xsl:template>
XML:
<?xml version="1.0" encoding="UTF-8"?>
<QueryResults>
<DataRow>
<Instance>1</Instance>
<Stream>1</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>A1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>1</Stream>
<DayOfWeek>2</DayOfWeek>
<DisplayStuff>B1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>1</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>C1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>2</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>A2</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>2</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>C2</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>3</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>A3</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>3</Stream>
<DayOfWeek>2</DayOfWeek>
<DisplayStuff>B3</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>3</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>C3</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>1</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>D1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>1</Stream>
<DayOfWeek>2</DayOfWeek>
<DisplayStuff>E1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>1</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>F1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>2</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>D2</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>2</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>E2</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>3</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>D3</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>3</Stream>
<DayOfWeek>2</DayOfWeek>
<DisplayStuff>E3</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>3</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>F3</DisplayStuff>
</DataRow>
</QueryResults>
嗯,你在路上转错了几个弯。看看这是否有助于您重回正轨:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="row-by-instance" match="DataRow" use="Instance" />
<xsl:key name="row-by-day" match="DataRow" use="DayOfWeek" />
<xsl:key name="row-by-stream" match="DataRow" use="concat(Instance, '|', Stream)" />
<xsl:template match="/QueryResults">
<!-- a column for each distinct day of week (in any instance) -->
<xsl:variable name="columns" select="DataRow[generate-id() = generate-id(key('row-by-day', DayOfWeek)[1])]" />
<!-- a table for each distinct instance -->
<xsl:for-each select="DataRow[count(. | key('row-by-instance', Instance)[1]) = 1]">
<xsl:variable name="instance-rows" select="key('row-by-instance', Instance)" />
<table border="1">
<!-- a row for each distinct stream in this instance -->
<xsl:for-each select="$instance-rows[generate-id() = generate-id(key('row-by-stream', concat(Instance, '|', Stream))[1])]">
<xsl:variable name="stream-rows" select="key('row-by-stream', concat(Instance, '|', Stream))" />
<tr>
<!-- a cell for each column -->
<xsl:for-each select="$columns">
<xsl:sort select="DayOfWeek" data-type="number" order="ascending"/>
<td>
<xsl:value-of select="$stream-rows[DayOfWeek = current()/DayOfWeek]/DisplayStuff" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
请注意,这会为所有 table 生成一组列,以便 table 对齐。如果您希望每个 table 都有自己的列(即跳过没有数据的星期几),那么您将不得不以不同的方式做事 - 最重要的是,您需要包括 Instance
在 row-by-day
键中。
这是我上一个问题的后续问题。我从 Table 格式的网格开始:
A1,B1,C1
A2,B2,C2
A3,B3,C3
现在这个 table 结果根据记录中的实例值最多重复 5 次。对于 table.
的每个实例,单元格中的值将不同我正在使用的 XML 为每条记录提供一个单元格值以及 DayOfWeek(列)、流(行)和实例(table 的迭代)值。
多亏了以前的帮助,我现在有了 XSLT,它可以让我创建一个网格(列 x 行)。但是,当我添加一个额外的键(逐行)以遍历实例时,XSLT 失败。
目标结果如下:
Instance 1
A1,B1,C1
A2, ,C2
A3,B3,C3
Instance 2
D1,E1,F1
D2, ,F2
D3,E3,F3
最多可以有 5 个实例,一周最多 7 天,行数任意。
更新 我已经根据 Michael 的贡献更新了 XSLT,但我仍然不在那里。当前结果为
A1 A1 A1 A1 B1 B1 B1 C1 C1 C1 C1
A2 A2 A2 A2 C2 C2 C2 C2
A3 A3 A3 A3 B3 B3 B3 C3 C3 C3 C3
A1 A1 A1 A1 B1 B1 B1 C1 C1 C1 C1
A2 A2 A2 A2 C2 C2 C2 C2
A3 A3 A3 A3 B3 B3 B3 C3 C3 C3 C3
我有两个 table 的迭代,但它们包含相同的数据,并且列重复次数太多!
XSL:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="row-by-instance" match="DataRow" use="Instance" />
<xsl:key name="row-by-stream" match="DataRow" use="concat(Instance, '|', Stream)" />
<xsl:key name="row-by-day" match="DataRow" use="concat(Instance, '|', Stream,'|',DayOfWeek)" />
<xsl:template match="/QueryResults">
<!-- a column for each distinct day of week -->
<xsl:variable name="columns" select="DataRow[generate-id() = generate-id(key('row-by-day',concat(Instance, '|', DayOfWeek))[1])]" />
<xsl:for-each select="DataRow[count(. | key('row-by-instance', Instance)[1]) = 1]">
<table border="1">
<!-- a row for each distinct stream -->
<!--<xsl:for-each select="DataRow[count(. | key('row-by-stream', Instance)[1]) = 1]">-->
<xsl:for-each select="key('row-by-instance', Instance)[count(. | key('row-by-stream', concat(Instance, '|', Stream))[1]) = 1]">
<xsl:variable name="stream" select="key('row-by-stream', concat(Instance, '|', Stream))" />
<tr>
<!-- a cell for each column -->
<xsl:for-each select="key('row-by-instance', Instance)[count(. | key('row-by-day', concat(Instance, '|', Stream,'|',DayOfWeek))[1]) = 1]">
<xsl:sort select="DayOfWeek" data-type="number" order="ascending"/>
<td>
<xsl:value-of select="$stream[DayOfWeek = current()/DayOfWeek]/DisplayStuff" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:for-each>
</xsl:template>
XML:
<?xml version="1.0" encoding="UTF-8"?>
<QueryResults>
<DataRow>
<Instance>1</Instance>
<Stream>1</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>A1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>1</Stream>
<DayOfWeek>2</DayOfWeek>
<DisplayStuff>B1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>1</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>C1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>2</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>A2</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>2</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>C2</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>3</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>A3</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>3</Stream>
<DayOfWeek>2</DayOfWeek>
<DisplayStuff>B3</DisplayStuff>
</DataRow>
<DataRow>
<Instance>1</Instance>
<Stream>3</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>C3</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>1</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>D1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>1</Stream>
<DayOfWeek>2</DayOfWeek>
<DisplayStuff>E1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>1</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>F1</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>2</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>D2</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>2</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>E2</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>3</Stream>
<DayOfWeek>1</DayOfWeek>
<DisplayStuff>D3</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>3</Stream>
<DayOfWeek>2</DayOfWeek>
<DisplayStuff>E3</DisplayStuff>
</DataRow>
<DataRow>
<Instance>2</Instance>
<Stream>3</Stream>
<DayOfWeek>3</DayOfWeek>
<DisplayStuff>F3</DisplayStuff>
</DataRow>
</QueryResults>
嗯,你在路上转错了几个弯。看看这是否有助于您重回正轨:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="row-by-instance" match="DataRow" use="Instance" />
<xsl:key name="row-by-day" match="DataRow" use="DayOfWeek" />
<xsl:key name="row-by-stream" match="DataRow" use="concat(Instance, '|', Stream)" />
<xsl:template match="/QueryResults">
<!-- a column for each distinct day of week (in any instance) -->
<xsl:variable name="columns" select="DataRow[generate-id() = generate-id(key('row-by-day', DayOfWeek)[1])]" />
<!-- a table for each distinct instance -->
<xsl:for-each select="DataRow[count(. | key('row-by-instance', Instance)[1]) = 1]">
<xsl:variable name="instance-rows" select="key('row-by-instance', Instance)" />
<table border="1">
<!-- a row for each distinct stream in this instance -->
<xsl:for-each select="$instance-rows[generate-id() = generate-id(key('row-by-stream', concat(Instance, '|', Stream))[1])]">
<xsl:variable name="stream-rows" select="key('row-by-stream', concat(Instance, '|', Stream))" />
<tr>
<!-- a cell for each column -->
<xsl:for-each select="$columns">
<xsl:sort select="DayOfWeek" data-type="number" order="ascending"/>
<td>
<xsl:value-of select="$stream-rows[DayOfWeek = current()/DayOfWeek]/DisplayStuff" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
请注意,这会为所有 table 生成一组列,以便 table 对齐。如果您希望每个 table 都有自己的列(即跳过没有数据的星期几),那么您将不得不以不同的方式做事 - 最重要的是,您需要包括 Instance
在 row-by-day
键中。